Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1ba9bacda | ||
|
|
169022923c | ||
|
|
4acf27234e | ||
|
|
e9977f2a2c | ||
|
|
df8d809506 | ||
|
|
4d89fec9ff | ||
|
|
27b641d048 | ||
|
|
e475c0df06 | ||
|
|
9877129815 | ||
|
|
3376001d45 | ||
|
|
0cbd884234 | ||
|
|
3e8327e934 | ||
|
|
ca9d88f47b | ||
|
|
bf92ffffa3 | ||
|
|
eccec21ada | ||
|
|
03aaf7db6a | ||
|
|
6d9e0482b4 | ||
|
|
34f2328a79 | ||
|
|
2569193b05 | ||
|
|
b935ec3d19 | ||
|
|
e0e6b0d9a5 | ||
|
|
580218d495 | ||
|
|
519f280fa5 | ||
|
|
a33ee13bb4 | ||
|
|
0c70cc7e5a | ||
|
|
2cba346ff5 | ||
|
|
db2509edb3 | ||
|
|
e3063d6cd6 | ||
|
|
8d30e8cee8 | ||
|
|
ff2f1998ad | ||
|
|
7942ee438a | ||
|
|
f322dfb1d4 | ||
|
|
a7f5ddfe0d | ||
|
|
0cdfb75fd0 | ||
|
|
35624a12d9 | ||
|
|
9b147cc57c | ||
|
|
10e13cfece | ||
|
|
7b2eb7bc47 | ||
|
|
ab1cb802d8 | ||
|
|
366cdd8df0 | ||
|
|
bc3cfb1373 | ||
|
|
db6792af2e | ||
|
|
a1485fb7cd | ||
|
|
c72c309218 | ||
|
|
58899a9ed3 | ||
|
|
0823c70460 | ||
|
|
e5c29a3975 | ||
|
|
1174ae99c9 | ||
|
|
e2d3680038 | ||
|
|
8630893cb1 | ||
|
|
53598b970d | ||
|
|
89de00ac36 | ||
|
|
d5ddf07958 | ||
|
|
30dcf4a14a | ||
|
|
a87710e4bc | ||
|
|
a12f87fec2 | ||
|
|
8ba9bba094 | ||
|
|
1363571c14 | ||
|
|
80de666fcc | ||
|
|
ff0a2f84fa | ||
|
|
0676f145bc | ||
|
|
e19ae2bf60 | ||
|
|
7782d930d5 | ||
|
|
d1a53fe29b | ||
|
|
c484cf286c | ||
|
|
f8882c4da6 |
@@ -11,7 +11,7 @@ jobs:
|
||||
name: "Update Base Translation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Update Base Translation
|
||||
run: ./.github/workflows/scripts/common/update_base_translation.sh
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
|
||||
4
.github/workflows/lint_gamedb.yml
vendored
@@ -18,12 +18,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
npm install -g ajv-cli prettier
|
||||
sudo apt-get -y install yamllint
|
||||
pip install yamllint
|
||||
|
||||
- name: Validate YAML
|
||||
run: |
|
||||
|
||||
2
.github/workflows/linux_build_flatpak.yml
vendored
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
# 10 here, since the odds of having 10 untagged commits in a row should be slim to none
|
||||
|
||||
12
.github/workflows/linux_build_qt.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -104,13 +104,13 @@ jobs:
|
||||
sudo tools/retry.sh apt-add-repository -n 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main'
|
||||
sudo tools/retry.sh apt-get update
|
||||
sudo tools/retry.sh apt-get -y install \
|
||||
build-essential ccache clang-17 cmake curl extra-cmake-modules git libasound2-dev libaio-dev libavcodec-dev libavformat-dev libavutil-dev \
|
||||
build-essential ccache clang-17 cmake curl extra-cmake-modules git libasound2-dev libaio-dev \
|
||||
libcurl4-openssl-dev libdbus-1-dev libdecor-0-dev libegl-dev libevdev-dev libfontconfig-dev libfreetype-dev libfuse2 libgtk-3-dev libgudev-1.0-dev \
|
||||
libharfbuzz-dev libinput-dev libopengl-dev libpcap-dev libpipewire-0.3-dev libpulse-dev libssl-dev libswresample-dev libswscale-dev libudev-dev \
|
||||
libwayland-dev libx11-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev libxcb-glx0-dev libxcb-icccm4-dev \
|
||||
libharfbuzz-dev libinput-dev libopengl-dev libopus-dev libpcap-dev libpipewire-0.3-dev libpulse-dev libssl-dev libudev-dev libva-dev libvpl2 libvpl-dev \
|
||||
libwayland-dev libx11-dev libx11-xcb-dev libx264-dev libxcb1-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev libxcb-glx0-dev libxcb-icccm4-dev \
|
||||
libxcb-image0-dev libxcb-keysyms1-dev libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-shape0-dev \
|
||||
libxcb-shm0-dev libxcb-sync-dev libxcb-util-dev libxcb-xfixes0-dev libxcb-xinput-dev libxcb-xkb-dev libxext-dev libxkbcommon-x11-dev libxrandr-dev \
|
||||
lld-17 llvm-17 ninja-build patchelf pkg-config zlib1g-dev
|
||||
lld-17 llvm-17 nasm ninja-build patchelf pkg-config zlib1g-dev
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: .github/workflows/scripts/linux/build-dependencies-qt.sh "$HOME/deps"
|
||||
run: BUILD_FFMPEG=1 .github/workflows/scripts/linux/build-dependencies-qt.sh "$HOME/deps"
|
||||
|
||||
- name: Download patches
|
||||
run: |
|
||||
|
||||
2
.github/workflows/macos_build.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
|
||||
4
.github/workflows/release_cut_new.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
outputs:
|
||||
new_tag: ${{ steps.tag_version.outputs.new_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
15
.github/workflows/scripts/linux/appimage-qt.sh
vendored
@@ -41,12 +41,9 @@ BINARY=pcsx2-qt
|
||||
APPDIRNAME=PCSX2.AppDir
|
||||
STRIP=strip
|
||||
|
||||
# Need both libharfbuzz.so and libharfbuzz.so.0 for bundled libs
|
||||
|
||||
declare -a MANUAL_LIBS=(
|
||||
"libshaderc_shared.so.1"
|
||||
"libharfbuzz.so.0"
|
||||
"libharfbuzz.so"
|
||||
"libfreetype.so.6"
|
||||
)
|
||||
|
||||
@@ -74,18 +71,6 @@ fi
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
rm -fr "$OUTDIR"
|
||||
|
||||
# Our deps build dosn't create libharfbuzz.so.0, so we have to symlink it here
|
||||
hbpath=$(find "$DEPSDIR" -name "libharfbuzz.so")
|
||||
if [ ! -f "$hbpath" ]; then
|
||||
echo "Missing harfbuzz. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$hbpath.0" ]; then
|
||||
echo "Symlinking libharfbuzz.so.0"
|
||||
ln -s "$hbpath" "$hbpath.0"
|
||||
fi
|
||||
|
||||
echo "Locating extra libraries..."
|
||||
EXTRA_LIBS_ARGS=()
|
||||
for lib in "${MANUAL_LIBS[@]}"; do
|
||||
|
||||
@@ -7,6 +7,10 @@ if [ "$#" -ne 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The bundled ffmpeg has a lot of things disabled to reduce code size.
|
||||
# Users may want to use system ffmpeg for additional features
|
||||
: ${BUILD_FFMPEG:=0}
|
||||
|
||||
SCRIPTDIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
INSTALLDIR="$1"
|
||||
@@ -14,16 +18,19 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FFMPEG=8.0
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
NVENC=11.1.5.3
|
||||
SDL=SDL3-3.2.26
|
||||
QT=6.10.0
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
LZ4=1.10.0
|
||||
VULKAN=1.4.328.1
|
||||
ZSTD=1.5.7
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
@@ -37,7 +44,10 @@ SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
export PKG_CONFIG_PATH="$INSTALLDIR/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
@@ -47,13 +57,15 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
2974b91062197e0527dffa3aadd8fe3bfa6681ae45f5ff9181bc0ca6479abd59 nv-codec-headers-$NVENC.tar.gz
|
||||
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
ead4623bcb54a32257c5b3e3a5aec6d16ec96f4cda58d2e003f5a0c16f72046d qtbase-everywhere-src-$QT.tar.xz
|
||||
64450a52507c540de53616ed5e516df0e0905a99d3035ddfaa690f2b3f7c0cea qtimageformats-everywhere-src-$QT.tar.xz
|
||||
5ed2c0e04d5e73ff75c2a2ed92db5dc1788ba70f704fc2b71bc21644beda2533 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d86d5098cf3e3e599f37e18df477e65908fc8f036e10ea731b3469ec4fdbd02a qttools-everywhere-src-$QT.tar.xz
|
||||
326e8253cfd0cb5745238117f297da80e30ce8f4c1db81990497bd388b026cde qttranslations-everywhere-src-$QT.tar.xz
|
||||
603f2b0a259b24bd0fb14f880d7761b1d248118a42a6870cdbe8fdda4173761f qtwayland-everywhere-src-$QT.tar.xz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
|
||||
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
|
||||
49bf6db800227a6b2c971f4c5d03dd1e81297e7ffb296ce4a96437304f27cb13 qtwayland-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
@@ -75,6 +87,9 @@ curl -L \
|
||||
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/vulkan-sdk-$VULKAN.tar.gz" \
|
||||
-O "https://github.com/FFmpeg/nv-codec-headers/releases/download/n$NVENC/nv-codec-headers-$NVENC.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" \
|
||||
@@ -92,6 +107,37 @@ curl -L \
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
if [ "$BUILD_FFMPEG" -ne 0 ]; then
|
||||
echo "Installing vulkan headers..."
|
||||
rm -fr "Vulkan-Headers-vulkan-sdk-$VULKAN"
|
||||
tar xf "vulkan-sdk-$VULKAN.tar.gz"
|
||||
cd "Vulkan-Headers-vulkan-sdk-$VULKAN"
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing nvenc headers..."
|
||||
rm -fr "nv-codec-headers-$NVENC"
|
||||
tar xf "nv-codec-headers-$NVENC.tar.gz"
|
||||
make -C "nv-codec-headers-$NVENC" PREFIX="$INSTALLDIR" install
|
||||
|
||||
echo "Installing FFmpeg..."
|
||||
rm -fr "ffmpeg-$FFMPEG"
|
||||
tar xf "ffmpeg-$FFMPEG.tar.xz"
|
||||
cd "ffmpeg-$FFMPEG"
|
||||
CFLAGS="-Os $CFLAGS" CXXFLAGS="-Os $CXXFLAGS" \
|
||||
./configure --prefix="$INSTALLDIR" \
|
||||
--disable-all --disable-autodetect --disable-static --enable-shared \
|
||||
--enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale \
|
||||
--enable-gpl --enable-libx264 --enable-libopus --enable-vulkan --enable-ffnvcodec --enable-nvenc --enable-vaapi --enable-libvpl \
|
||||
--enable-encoder=ffv1,qtrle,libx264*,aac,flac,libopus,pcm_s16be,pcm_s16le,*_vulkan,*_qsv,*_nvenc,*_vaapi \
|
||||
--enable-muxer=avi,matroska,mov,mp3,mp4,wav \
|
||||
--enable-protocol=file
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
unzip "$LIBBACKTRACE.zip"
|
||||
@@ -165,7 +211,9 @@ echo "Building HarfBuzz..."
|
||||
rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
|
||||
# Add an SOVERSION to match system harfbuzz
|
||||
sed -i 's/PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)/PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE SOVERSION 0)/g' CMakeLists.txt
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -DHB_HAVE_GOBJECT=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
@@ -199,7 +247,7 @@ tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure -prefix "$INSTALLDIR" -release -dbus-linked -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -gtk -- -DFEATURE_dbus=ON -DFEATURE_icu=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
../configure -prefix "$INSTALLDIR" -release -dbus-linked -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -gtk -- --log-level=STATUS -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_dbus=ON -DFEATURE_icu=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
@@ -48,7 +48,7 @@ LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.10.0
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
@@ -89,11 +89,11 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
ead4623bcb54a32257c5b3e3a5aec6d16ec96f4cda58d2e003f5a0c16f72046d qtbase-everywhere-src-$QT.tar.xz
|
||||
64450a52507c540de53616ed5e516df0e0905a99d3035ddfaa690f2b3f7c0cea qtimageformats-everywhere-src-$QT.tar.xz
|
||||
5ed2c0e04d5e73ff75c2a2ed92db5dc1788ba70f704fc2b71bc21644beda2533 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d86d5098cf3e3e599f37e18df477e65908fc8f036e10ea731b3469ec4fdbd02a qttools-everywhere-src-$QT.tar.xz
|
||||
326e8253cfd0cb5745238117f297da80e30ce8f4c1db81990497bd388b026cde qttranslations-everywhere-src-$QT.tar.xz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
|
||||
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
|
||||
@@ -30,7 +30,7 @@ LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.10.0
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
@@ -70,11 +70,11 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
ead4623bcb54a32257c5b3e3a5aec6d16ec96f4cda58d2e003f5a0c16f72046d qtbase-everywhere-src-$QT.tar.xz
|
||||
64450a52507c540de53616ed5e516df0e0905a99d3035ddfaa690f2b3f7c0cea qtimageformats-everywhere-src-$QT.tar.xz
|
||||
5ed2c0e04d5e73ff75c2a2ed92db5dc1788ba70f704fc2b71bc21644beda2533 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d86d5098cf3e3e599f37e18df477e65908fc8f036e10ea731b3469ec4fdbd02a qttools-everywhere-src-$QT.tar.xz
|
||||
326e8253cfd0cb5745238117f297da80e30ce8f4c1db81990497bd388b026cde qttranslations-everywhere-src-$QT.tar.xz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
|
||||
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
@@ -237,9 +237,6 @@ cd "qtbase-everywhere-src-$QT"
|
||||
# Patch Qt to support macOS 11
|
||||
patch -p1 < "$SCRIPTDIR/qt-macos11compat.patch"
|
||||
|
||||
# Patch Qt to fix a bug with message boxes on Tahoe
|
||||
patch -p1 < "$SCRIPTDIR/clickbutton.patch"
|
||||
|
||||
# since we don't have a direct reference to QtSvg, it doesn't deployed directly from the main binary
|
||||
# (only indirectly from iconengines), and the libqsvg.dylib imageformat plugin does not get deployed.
|
||||
# We could run macdeployqt twice, but that's even more janky than patching it.
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
--- a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
|
||||
+++ b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
|
||||
@@ -88,6 +88,11 @@ bool QCocoaMessageDialog::show(Qt::WindowModality windowModality)
|
||||
qCWarning(lcQpaDialogs, "Cannot run window modal dialog without parent window");
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ // Tahoe has issues with window-modal alert buttons not responding to mouse
|
||||
+ if (windowModality == Qt::WindowModal
|
||||
+ && QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe)
|
||||
+ return false;
|
||||
|
||||
// And without options we don't know what to show
|
||||
if (!options())
|
||||
|
||||
# Source https://codereview.qt-project.org/c/qt/qtbase/+/689796
|
||||
@@ -1,5 +1,4 @@
|
||||
diff --git a/.cmake.conf b/.cmake.conf
|
||||
index 9a21ff42a74..d6707ba7dff 100644
|
||||
--- a/.cmake.conf
|
||||
+++ b/.cmake.conf
|
||||
@@ -51,7 +51,7 @@ set(QT_MAX_NEW_POLICY_CMAKE_VERSION_QT_APPLE "3.21")
|
||||
@@ -12,7 +11,6 @@ index 9a21ff42a74..d6707ba7dff 100644
|
||||
|
||||
set(QT_SUPPORTED_MIN_IOS_SDK_VERSION "17")
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index d3a14fc67eb..1553b956fe3 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -12,6 +12,10 @@ cmake_minimum_required(VERSION 3.16)
|
||||
@@ -27,7 +25,6 @@ index d3a14fc67eb..1553b956fe3 100644
|
||||
|
||||
qt_internal_check_if_path_has_symlinks("${CMAKE_BINARY_DIR}")
|
||||
diff --git a/src/corelib/global/qsysinfo.cpp b/src/corelib/global/qsysinfo.cpp
|
||||
index ae762c0cc6d..9171a5736b4 100644
|
||||
--- a/src/corelib/global/qsysinfo.cpp
|
||||
+++ b/src/corelib/global/qsysinfo.cpp
|
||||
@@ -1027,7 +1027,7 @@ QByteArray QSysInfo::machineUniqueId()
|
||||
@@ -40,10 +37,9 @@ index ae762c0cc6d..9171a5736b4 100644
|
||||
CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman);
|
||||
return QByteArray(uuid);
|
||||
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
|
||||
index 9f27dbe694e..c023a48cad3 100644
|
||||
--- a/src/corelib/kernel/qcore_mac.mm
|
||||
+++ b/src/corelib/kernel/qcore_mac.mm
|
||||
@@ -372,7 +372,7 @@ bool qt_apple_runningWithLiquidGlass()
|
||||
@@ -367,7 +367,7 @@ bool qt_apple_runningWithLiquidGlass()
|
||||
return config;
|
||||
#endif
|
||||
|
||||
@@ -52,8 +48,50 @@ index 9f27dbe694e..c023a48cad3 100644
|
||||
if (!nvram) {
|
||||
qWarning("Failed to locate NVRAM entry in IO registry");
|
||||
return {};
|
||||
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
|
||||
--- a/src/gui/platform/darwin/qappleiconengine.mm
|
||||
+++ b/src/gui/platform/darwin/qappleiconengine.mm
|
||||
@@ -366,12 +366,16 @@
|
||||
weight:NSFontWeightRegular
|
||||
scale:NSImageSymbolScaleLarge];
|
||||
|
||||
+ auto *primaryColor = [NSColor colorWithSRGBRed:color.redF()
|
||||
+ green:color.greenF()
|
||||
+ blue:color.blueF()
|
||||
+ alpha:color.alphaF()];
|
||||
+
|
||||
+ if (@available(macOS 13, *)) {
|
||||
+
|
||||
// Apply tint color first, which switches the configuration to palette mode
|
||||
config = [config configurationByApplyingConfiguration:
|
||||
- [NSImageSymbolConfiguration configurationWithPaletteColors:@[
|
||||
- [NSColor colorWithSRGBRed:color.redF() green:color.greenF()
|
||||
- blue:color.blueF() alpha:color.alphaF()]
|
||||
- ]]];
|
||||
+ [NSImageSymbolConfiguration configurationWithPaletteColors:@[primaryColor]]];
|
||||
|
||||
// Then switch back to monochrome, as palette mode gives a different look
|
||||
// than monochrome, even with a single color.
|
||||
@@ -379,6 +383,18 @@
|
||||
[NSImageSymbolConfiguration configurationPreferringMonochrome]];
|
||||
|
||||
return [image imageWithSymbolConfiguration:config];
|
||||
+
|
||||
+ } else {
|
||||
+ NSImage *configuredImage = [image imageWithSymbolConfiguration:config];
|
||||
+ return [NSImage imageWithSize:configuredImage.size flipped:NO
|
||||
+ drawingHandler:^BOOL(NSRect) {
|
||||
+ [primaryColor set];
|
||||
+ NSRect imageRect = {NSZeroPoint, configuredImage.size};
|
||||
+ [configuredImage drawInRect:imageRect];
|
||||
+ NSRectFillUsingOperation(imageRect, NSCompositingOperationSourceIn);
|
||||
+ return YES;
|
||||
+ }];
|
||||
+ }
|
||||
}
|
||||
#elif defined(QT_PLATFORM_UIKIT)
|
||||
auto *configuredImage(const UIImage *image, const QColor &color)
|
||||
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
index 6b33d94d58c..867389e4c93 100644
|
||||
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
@@ -323,6 +323,8 @@ a normal (not maximized or full screen) top-level window.
|
||||
|
||||
@@ -48,7 +48,7 @@ set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1650
|
||||
set LIBPNGLONG=1.6.50
|
||||
set SDL=SDL3-3.2.26
|
||||
set QT=6.10.0
|
||||
set QT=6.10.1
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
set LZ4=1.10.0
|
||||
@@ -72,11 +72,11 @@ call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 739356eef1192fff9d641c320a8f5ef4a10506b8927def4b9ceb764c7e947369 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" d3b5379edcace266273d789249b6d68ae9495ec1b0b562ba6d039034cd315d8e || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" ac2fe34a9f1c1451b6785474e9b1b64eb59edef6553be3d630240f16a730456d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c12f8bfb617e4a03da104be36f6966ba7f64bee331f0095da1a649a1149796d2 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c6d0f0a512304ad87b20f5ff604442dd8d55769d659576ecfe5462fcd7bb9b7d || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" e6cc1ebf62cf37d81f3b86990086108518037bb383e75da327f297cc4fc1ae36 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c43f471a808b07fc541528410e94ce89c6745bdc1d744492e19911d35fbf7d33 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 2d828d8c999fdd18167937c071781c22321c643b04a106c714411c2356cdb26d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" ddd74a417d2397eb085d047a9b6ba52b76e748055817f728fe691f8456035d23 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" db8e49ed50912c3c064a4f9ada7791c09eccec5a8d53463a19608eaab17679f0 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 868eb651e395d48ade5932ef2c386e606e054eb5888ebe5284fbd8cb63ed935a || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
@@ -264,7 +264,7 @@ rmdir /S /Q "QtApng-%QTAPNG%"
|
||||
%SEVENZIP% x "QtApng-%QTAPNG%.zip" || goto error
|
||||
cd "QtApng-%QTAPNG%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\qtapng-cmake.patch" || goto error
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% %QTAPNGBUILDSPEC% || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" %FORCEPDB% %QTAPNGBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
@@ -46,7 +46,7 @@ set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.26
|
||||
set LIBPNGLONG=1.6.50
|
||||
set QT=6.10.0
|
||||
set QT=6.10.1
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
set LZ4=1.10.0
|
||||
@@ -70,11 +70,11 @@ call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 739356eef1192fff9d641c320a8f5ef4a10506b8927def4b9ceb764c7e947369 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" d3b5379edcace266273d789249b6d68ae9495ec1b0b562ba6d039034cd315d8e || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" ac2fe34a9f1c1451b6785474e9b1b64eb59edef6553be3d630240f16a730456d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c12f8bfb617e4a03da104be36f6966ba7f64bee331f0095da1a649a1149796d2 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c6d0f0a512304ad87b20f5ff604442dd8d55769d659576ecfe5462fcd7bb9b7d || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" e6cc1ebf62cf37d81f3b86990086108518037bb383e75da327f297cc4fc1ae36 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c43f471a808b07fc541528410e94ce89c6745bdc1d744492e19911d35fbf7d33 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 2d828d8c999fdd18167937c071781c22321c643b04a106c714411c2356cdb26d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" ddd74a417d2397eb085d047a9b6ba52b76e748055817f728fe691f8456035d23 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" db8e49ed50912c3c064a4f9ada7791c09eccec5a8d53463a19608eaab17679f0 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 868eb651e395d48ade5932ef2c386e606e054eb5888ebe5284fbd8cb63ed935a || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
|
||||
2
.github/workflows/windows_build_matrix.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
- name: Verify VS Project Files
|
||||
run: .github\workflows\scripts\windows\validate-vs-filters.ps1
|
||||
|
||||
|
||||
2
.github/workflows/windows_build_qt.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Configure MSBuild Clang Version
|
||||
if: inputs.configuration != 'CMake'
|
||||
|
||||
24
3rdparty/ccc/src/ccc/symbol_database.cpp
vendored
@@ -113,13 +113,27 @@ typename SymbolList<SymbolType>::AddressToHandleMapIterators SymbolList<SymbolTy
|
||||
template <typename SymbolType>
|
||||
typename SymbolList<SymbolType>::AddressToHandleMapIterators SymbolList<SymbolType>::handles_from_address_range(AddressRange range) const
|
||||
{
|
||||
if(range.low.valid()) {
|
||||
return {m_address_to_handle.lower_bound(range.low.value), m_address_to_handle.lower_bound(range.high.value)};
|
||||
} else if(range.high.valid()) {
|
||||
return {m_address_to_handle.begin(), m_address_to_handle.lower_bound(range.high.value)};
|
||||
typename AddressToHandleMap::const_iterator begin, end;
|
||||
if (range.low.valid() && range.high.valid()) {
|
||||
if (range.low.value < range.high.value) {
|
||||
begin = m_address_to_handle.lower_bound(range.low.value);
|
||||
end = m_address_to_handle.lower_bound(range.high.value);
|
||||
} else {
|
||||
begin = m_address_to_handle.end();
|
||||
end = m_address_to_handle.end();
|
||||
}
|
||||
} else if (range.low.valid()) {
|
||||
begin = m_address_to_handle.lower_bound(range.low.value);
|
||||
end = m_address_to_handle.end();
|
||||
} else if (range.high.valid()) {
|
||||
begin = m_address_to_handle.begin();
|
||||
end = m_address_to_handle.lower_bound(range.high.value);
|
||||
} else {
|
||||
return {m_address_to_handle.end(), m_address_to_handle.end()};
|
||||
begin = m_address_to_handle.end();
|
||||
end = m_address_to_handle.end();
|
||||
}
|
||||
|
||||
return {begin, end};
|
||||
}
|
||||
|
||||
template <typename SymbolType>
|
||||
|
||||
@@ -175,7 +175,6 @@
|
||||
030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000c0160000e105000000000000,Dual 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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows,
|
||||
030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
@@ -839,6 +838,7 @@
|
||||
03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c0160000e105000000000000,XinMo Dual Arcade,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
|
||||
030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows,
|
||||
@@ -1119,6 +1119,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,
|
||||
03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c0160000e105000000040000,Ultimate Atari Fight Stick,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,platform:Mac OS X,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X,
|
||||
030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,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,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
@@ -1774,6 +1775,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
</action>
|
||||
<action name="actionAnalyse">
|
||||
<property name="icon">
|
||||
<iconset theme="magnifier-line"/>
|
||||
<iconset theme="search-line"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Analyze</string>
|
||||
|
||||
@@ -144,12 +144,12 @@ void DockMenuBar::onLockStateChanged(bool layout_locked)
|
||||
if (layout_locked)
|
||||
{
|
||||
m_layout_locked_toggle->setText(tr("Layout Locked"));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("padlock-lock")));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("lock-fill")));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layout_locked_toggle->setText(tr("Layout Unlocked"));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("padlock-unlock")));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("lock-unlock-fill")));
|
||||
}
|
||||
|
||||
m_ignore_lock_state_changed = false;
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
CLONE_LAYOUT,
|
||||
};
|
||||
|
||||
// Bundles together a creation mode and inital state.
|
||||
// Bundles together a creation mode and a default dock layout index.
|
||||
using InitialState = std::pair<CreationMode, size_t>;
|
||||
|
||||
// Create a "New Layout" dialog.
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
const ccc::SymbolDatabase& database,
|
||||
const SymbolTreeDisplayOptions& display_options);
|
||||
|
||||
// Write the value back to the VM memory. Returns true on success.
|
||||
// Write the value back to the VM memory. Returns true if the data changed.
|
||||
bool writeToVM(
|
||||
QVariant value,
|
||||
DebugInterface& cpu,
|
||||
|
||||
@@ -13,7 +13,7 @@ ThreadModel::ThreadModel(DebugInterface& cpu, QObject* parent)
|
||||
|
||||
int ThreadModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_cpu.GetThreadList().size();
|
||||
return static_cast<int>(m_threads.size());
|
||||
}
|
||||
|
||||
int ThreadModel::columnCount(const QModelIndex&) const
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "common/Console.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QResizeEvent>
|
||||
@@ -32,6 +33,10 @@
|
||||
DisplaySurface::DisplaySurface()
|
||||
: QWindow()
|
||||
{
|
||||
m_resize_debounce_timer = new QTimer(this);
|
||||
m_resize_debounce_timer->setSingleShot(true);
|
||||
m_resize_debounce_timer->setTimerType(Qt::PreciseTimer);
|
||||
connect(m_resize_debounce_timer, &QTimer::timeout, this, &DisplaySurface::onResizeDebounceTimer);
|
||||
}
|
||||
|
||||
DisplaySurface::~DisplaySurface()
|
||||
@@ -245,6 +250,11 @@ void DisplaySurface::handleKeyInputEvent(QEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySurface::onResizeDebounceTimer()
|
||||
{
|
||||
emit windowResizedEvent(m_pending_window_width, m_pending_window_height, m_pending_window_scale);
|
||||
}
|
||||
|
||||
bool DisplaySurface::event(QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
@@ -355,10 +365,17 @@ bool DisplaySurface::event(QEvent* event)
|
||||
// avoid spamming resize events for paint events (sent on move on windows)
|
||||
if (m_last_window_width != scaled_width || m_last_window_height != scaled_height || m_last_window_scale != dpr)
|
||||
{
|
||||
m_pending_window_width = scaled_width;
|
||||
m_pending_window_height = scaled_height;
|
||||
m_pending_window_scale = dpr;
|
||||
|
||||
m_last_window_width = scaled_width;
|
||||
m_last_window_height = scaled_height;
|
||||
m_last_window_scale = dpr;
|
||||
emit windowResizedEvent(scaled_width, scaled_height, dpr);
|
||||
// qt spams resize events, sometimes several time per ms.
|
||||
// since a vulkan resize swap chain event takes between 15 to 25ms this is,
|
||||
// need less to say, unwanted.
|
||||
m_resize_debounce_timer->start(100);
|
||||
}
|
||||
|
||||
updateCenterPos();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "common/WindowInfo.h"
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QDragMoveEvent>
|
||||
#include <QtGui/QWindow>
|
||||
#include <optional>
|
||||
@@ -42,6 +43,9 @@ protected:
|
||||
bool event(QEvent* event) override;
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onResizeDebounceTimer();
|
||||
|
||||
private:
|
||||
bool isActuallyFullscreen() const;
|
||||
void updateCenterPos();
|
||||
@@ -60,5 +64,10 @@ private:
|
||||
u32 m_last_window_height = 0;
|
||||
float m_last_window_scale = 1.0f;
|
||||
|
||||
QTimer* m_resize_debounce_timer = nullptr;
|
||||
u32 m_pending_window_width = 0;
|
||||
u32 m_pending_window_height = 0;
|
||||
float m_pending_window_scale = 1.0f;
|
||||
|
||||
QWidget* m_container = nullptr;
|
||||
};
|
||||
|
||||
@@ -256,8 +256,6 @@ void GameListWidget::initialize()
|
||||
|
||||
m_table_view = new QTableView(m_ui.stack);
|
||||
m_table_view->setModel(m_sort_model);
|
||||
m_table_view->setSortingEnabled(true);
|
||||
m_table_view->horizontalHeader()->setSectionsMovable(true);
|
||||
m_table_view->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_table_view->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_table_view->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
@@ -265,8 +263,9 @@ void GameListWidget::initialize()
|
||||
m_table_view->setMouseTracking(true);
|
||||
m_table_view->setShowGrid(false);
|
||||
m_table_view->setCurrentIndex(QModelIndex());
|
||||
m_table_view->horizontalHeader()->setHighlightSections(false);
|
||||
m_table_view->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_table_view->horizontalHeader()->setHighlightSections(false);
|
||||
m_table_view->horizontalHeader()->setSectionsMovable(true);
|
||||
m_table_view->verticalHeader()->hide();
|
||||
m_table_view->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
|
||||
|
||||
@@ -738,8 +737,8 @@ void GameListWidget::resizeTableViewColumnsToFit()
|
||||
QtUtils::ResizeColumnsForTableView(m_table_view, {
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Type],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Serial],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Title],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_FileTitle],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Type],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_CRC],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_TimePlayed],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_LastPlayed],
|
||||
|
||||
@@ -1099,7 +1099,7 @@ bool MainWindow::shouldMouseLock() const
|
||||
if (!Host::GetBoolSettingValue("EmuCore", "EnableMouseLock", false))
|
||||
return false;
|
||||
|
||||
if (m_display_created == false || m_display_surface == nullptr && !isRenderingToMain())
|
||||
if (m_display_created == false || m_display_surface == nullptr)
|
||||
return false;
|
||||
|
||||
bool windowsHidden = (!g_debugger_window || g_debugger_window->isHidden()) &&
|
||||
@@ -2570,11 +2570,21 @@ void MainWindow::checkMousePosition(int x, int y)
|
||||
const QSize logicalSize = displayWindow->size();
|
||||
const QPoint logicalPosition = displayWindow->position() + displayWindow->parent()->position();
|
||||
|
||||
// The offset to the origin of the current screen is in device-independent pixels while the origin itself is native!
|
||||
// The logicalPosition is the sum of these two values, so we need to separate them and only scale the offset
|
||||
const QScreen* screen = displayWindow->screen();
|
||||
|
||||
// If we fail to get the screen associated with the window, avoid mouse locking as it's probably in an unexpected position.
|
||||
if (!screen)
|
||||
return;
|
||||
|
||||
const QPoint screenPosition = screen->geometry().topLeft();
|
||||
|
||||
// physical frame rect
|
||||
const qreal scale = displayWindow->devicePixelRatio();
|
||||
const QRectF physicalBounds(
|
||||
logicalPosition.x() * scale,
|
||||
logicalPosition.y() * scale,
|
||||
screenPosition.x() + (logicalPosition.x() - screenPosition.x()) * scale,
|
||||
screenPosition.y() + (logicalPosition.y() - screenPosition.y()) * scale,
|
||||
logicalSize.width() * scale,
|
||||
logicalSize.height() * scale);
|
||||
|
||||
|
||||
@@ -855,7 +855,7 @@
|
||||
</action>
|
||||
<action name="actionDebugger">
|
||||
<property name="icon">
|
||||
<iconset theme="heart-circle-line"/>
|
||||
<iconset theme="bug-line"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Open Debugger</string>
|
||||
|
||||
@@ -318,7 +318,9 @@ void EmuThread::loadState(const QString& filename)
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
VMManager::LoadState(filename.toUtf8().constData());
|
||||
Error error;
|
||||
if (!VMManager::LoadState(filename.toUtf8().constData(), &error))
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("QtHost", "Failed to Load State"), error.GetDescription());
|
||||
}
|
||||
|
||||
void EmuThread::loadStateFromSlot(qint32 slot, bool load_backup)
|
||||
@@ -332,7 +334,9 @@ void EmuThread::loadStateFromSlot(qint32 slot, bool load_backup)
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
VMManager::LoadStateFromSlot(slot, load_backup);
|
||||
Error error;
|
||||
if (!VMManager::LoadStateFromSlot(slot, load_backup, &error))
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("QtHost", "Failed to Load State"), error.GetDescription());
|
||||
}
|
||||
|
||||
void EmuThread::saveState(const QString& filename)
|
||||
|
||||
@@ -127,7 +127,25 @@ void AchievementLoginDialog::processLoginResult(bool result, const QString& mess
|
||||
}
|
||||
}
|
||||
|
||||
done(0);
|
||||
// Show success messagebox
|
||||
const std::string username = Host::GetBaseStringSettingValue("Achievements", "Username");
|
||||
QMessageBox::information(
|
||||
this, tr("Login Successful"),
|
||||
tr("Successfully logged in to RetroAchievements as %1.").arg(QString::fromStdString(username)));
|
||||
|
||||
m_ui.status->setText(tr("Successfully logged in as %1.").arg(QString::fromStdString(username)));
|
||||
m_ui.status->setStyleSheet("color: green; font-weight: bold;");
|
||||
|
||||
disconnect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &AchievementLoginDialog::loginClicked);
|
||||
|
||||
m_login->setVisible(false);
|
||||
QPushButton* dismissButton = m_ui.buttonBox->addButton(tr("&Dismiss"), QDialogButtonBox::AcceptRole);
|
||||
dismissButton->setDefault(true);
|
||||
dismissButton->setFocus();
|
||||
|
||||
connect(dismissButton, &QPushButton::clicked, this, [this]() { done(0); });
|
||||
|
||||
enableUI(false);
|
||||
}
|
||||
|
||||
void AchievementLoginDialog::connectUi()
|
||||
|
||||
@@ -114,22 +114,22 @@
|
||||
<property name="spacing">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="showFrameTimes">
|
||||
<property name="text">
|
||||
<string>Show Frame Times</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<item row="7" column="2">
|
||||
<widget class="QLabel" name="warningLabel">
|
||||
<property name="text">
|
||||
<string>Warnings For User</string>
|
||||
<string>Messages</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="showCPU">
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="showUsageCPU">
|
||||
<property name="text">
|
||||
<string>Show CPU Usage</string>
|
||||
</property>
|
||||
@@ -142,14 +142,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<item row="5" column="2">
|
||||
<widget class="QCheckBox" name="showInputRec">
|
||||
<property name="text">
|
||||
<string>Show Input Recording Status</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="2">
|
||||
<widget class="QCheckBox" name="showTextureReplacements">
|
||||
<property name="text">
|
||||
<string>Show Texture Replacement Status</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="showResolution">
|
||||
<property name="text">
|
||||
<string>Show Resolution</string>
|
||||
@@ -163,22 +170,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="showVPS">
|
||||
<property name="text">
|
||||
<string>Show VPS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QCheckBox" name="showGPU">
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="showUsageGPU">
|
||||
<property name="text">
|
||||
<string>Show GPU Usage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="showSpeed">
|
||||
<widget class="QCheckBox" name="showSpeedPercentages">
|
||||
<property name="text">
|
||||
<string>Show Speed Percentages</string>
|
||||
</property>
|
||||
@@ -187,46 +194,46 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="Column0_PerformanceAndStats">
|
||||
<property name="text">
|
||||
<string>Performance & Stats</string>
|
||||
<string>Performance Stats</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="showSettings">
|
||||
<property name="text">
|
||||
<string>Show Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="showGSStats">
|
||||
<property name="text">
|
||||
<string>Show Statistics</string>
|
||||
<string>Show GS Statistics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="showIndicators">
|
||||
<item row="8" column="0">
|
||||
<widget class="QCheckBox" name="showStatusIndicators">
|
||||
<property name="text">
|
||||
<string>Show Indicators</string>
|
||||
<string>Show Status Indicators</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<item row="4" column="2">
|
||||
<widget class="QCheckBox" name="showVideoCapture">
|
||||
<property name="text">
|
||||
<string>Show Video Capture Status</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="showInputs">
|
||||
<property name="text">
|
||||
<string>Show Inputs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<item row="8" column="2">
|
||||
<widget class="QCheckBox" name="warnAboutUnsafeSettings">
|
||||
<property name="text">
|
||||
<string>Warn About Unsafe Settings</string>
|
||||
@@ -254,7 +261,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<item row="2" column="2">
|
||||
<widget class="QCheckBox" name="showPatches">
|
||||
<property name="text">
|
||||
<string>Show Patches</string>
|
||||
@@ -375,22 +382,23 @@
|
||||
<tabstop>scale</tabstop>
|
||||
<tabstop>messagesPos</tabstop>
|
||||
<tabstop>performancePos</tabstop>
|
||||
<tabstop>showSpeed</tabstop>
|
||||
<tabstop>showSpeedPercentages</tabstop>
|
||||
<tabstop>showFPS</tabstop>
|
||||
<tabstop>showVPS</tabstop>
|
||||
<tabstop>showResolution</tabstop>
|
||||
<tabstop>showGSStats</tabstop>
|
||||
<tabstop>showUsageCPU</tabstop>
|
||||
<tabstop>showUsageGPU</tabstop>
|
||||
<tabstop>showStatusIndicators</tabstop>
|
||||
<tabstop>showFrameTimes</tabstop>
|
||||
<tabstop>showCPU</tabstop>
|
||||
<tabstop>showGPU</tabstop>
|
||||
<tabstop>showHardwareInfo</tabstop>
|
||||
<tabstop>showVersion</tabstop>
|
||||
<tabstop>showIndicators</tabstop>
|
||||
<tabstop>showSettings</tabstop>
|
||||
<tabstop>showPatches</tabstop>
|
||||
<tabstop>showInputs</tabstop>
|
||||
<tabstop>showVideoCapture</tabstop>
|
||||
<tabstop>showInputRec</tabstop>
|
||||
<tabstop>showTextureReplacements</tabstop>
|
||||
<tabstop>warnAboutUnsafeSettings</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
||||
@@ -225,22 +225,23 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_osd.scale, "EmuCore/GS", "OsdScale", 100.0f);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_osd.messagesPos, "EmuCore/GS", "OsdMessagesPos", static_cast<int>(OsdOverlayPos::TopLeft));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_osd.performancePos, "EmuCore/GS", "OsdPerformancePos", static_cast<int>(OsdOverlayPos::TopRight));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showSpeed, "EmuCore/GS", "OsdShowSpeed", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showSpeedPercentages, "EmuCore/GS", "OsdShowSpeed", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showFPS, "EmuCore/GS", "OsdShowFPS", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showVPS, "EmuCore/GS", "OsdShowVPS", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showCPU, "EmuCore/GS", "OsdShowCPU", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showGPU, "EmuCore/GS", "OsdShowGPU", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showResolution, "EmuCore/GS", "OsdShowResolution", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showGSStats, "EmuCore/GS", "OsdShowGSStats", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showIndicators, "EmuCore/GS", "OsdShowIndicators", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showUsageCPU, "EmuCore/GS", "OsdShowCPU", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showUsageGPU, "EmuCore/GS", "OsdShowGPU", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showStatusIndicators, "EmuCore/GS", "OsdShowIndicators", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showFrameTimes, "EmuCore/GS", "OsdShowFrameTimes", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showHardwareInfo, "EmuCore/GS", "OsdShowHardwareInfo", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showVersion, "EmuCore/GS", "OsdShowVersion", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showSettings, "EmuCore/GS", "OsdShowSettings", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showPatches, "EmuCore/GS", "OsdshowPatches", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showInputs, "EmuCore/GS", "OsdShowInputs", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showFrameTimes, "EmuCore/GS", "OsdShowFrameTimes", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showVersion, "EmuCore/GS", "OsdShowVersion", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showHardwareInfo, "EmuCore/GS", "OsdShowHardwareInfo", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showVideoCapture, "EmuCore/GS", "OsdShowVideoCapture", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showInputRec, "EmuCore/GS", "OsdShowInputRec", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.showTextureReplacements, "EmuCore/GS", "OsdShowTextureReplacements", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_osd.warnAboutUnsafeSettings, "EmuCore", "OsdWarnAboutUnsafeSettings", true);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -715,57 +716,62 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
|
||||
dialog()->registerWidgetHelp(m_osd.scale, tr("OSD Scale"), tr("100%"), tr("Scales the size of the onscreen OSD from 50% to 500%."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.messagesPos, tr("OSD Messages Position"), tr("Left (Default)"),
|
||||
tr("Shows on-screen-display messages when events occur such as save states being "
|
||||
tr("Position of on-screen-display messages when events occur such as save states being "
|
||||
"created/loaded, screenshots being taken, etc."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.performancePos, tr("OSD Statistics Position"), tr("Right (Default)"),
|
||||
tr("Shows a variety of on-screen performance data points as selected by the user."));
|
||||
dialog()->registerWidgetHelp(m_osd.performancePos, tr("OSD Performance Position"), tr("Right (Default)"),
|
||||
tr("Position of a variety of on-screen performance data points as selected by the user."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showSpeedPercentages, tr("Show Speed Percentages"), tr("Unchecked"),
|
||||
tr("Shows the current emulation speed of the system as a percentage."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showFPS, tr("Show FPS"), tr("Unchecked"),
|
||||
tr("Shows the internal frame rate of the game in the top-right corner of the display."));
|
||||
tr("Shows the number of internal video frames displayed per second by the system."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showVPS, tr("Show VPS"), tr("Unchecked"),
|
||||
tr("Shows the vsync rate of the emulator in the top-right corner of the display."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showSpeed, tr("Show Speed Percentages"), tr("Unchecked"),
|
||||
tr("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."));
|
||||
tr("Shows the number of V-syncs performed per second by the system."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showResolution, tr("Show Resolution"), tr("Unchecked"),
|
||||
tr("Shows the resolution of the game in the top-right corner of the display."));
|
||||
tr("Shows the internal resolution of the game."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showCPU, tr("Show CPU Usage"), tr("Unchecked"), tr("Shows host's CPU utilization."));
|
||||
dialog()->registerWidgetHelp(m_osd.showGSStats, tr("Show GS Statistics"), tr("Unchecked"),
|
||||
tr("Shows statistics about the emulated GS such as primitives and draw calls."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showGPU, tr("Show GPU Usage"), tr("Unchecked"), tr("Shows host's GPU utilization."));
|
||||
dialog()->registerWidgetHelp(m_osd.showUsageCPU, tr("Show CPU Usage"),
|
||||
tr("Unchecked"), tr("Shows the host's CPU utilization based on threads."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showGSStats, tr("Show Statistics"), tr("Unchecked"),
|
||||
tr("Shows counters for internal graphical utilization, useful for debugging."));
|
||||
dialog()->registerWidgetHelp(m_osd.showUsageGPU, tr("Show GPU Usage"),
|
||||
tr("Unchecked"), tr("Shows the host's GPU utilization."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showIndicators, tr("Show Indicators"), tr("Checked"),
|
||||
tr("Shows OSD icon indicators for emulation states such as Pausing, Turbo, Fast-Forward, and Slow-Motion."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showSettings, tr("Show Settings"), tr("Unchecked"),
|
||||
tr("Displays various settings and the current values of those settings, useful for debugging."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showPatches, tr("Show Patches"), tr("Unchecked"),
|
||||
tr("Shows the amount of currently active patches/cheats on the bottom-right corner of the display."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showInputs, tr("Show Inputs"), tr("Unchecked"),
|
||||
tr("Shows the current controller state of the system in the bottom-left corner of the display."));
|
||||
dialog()->registerWidgetHelp(m_osd.showStatusIndicators, tr("Show Status Indicators"), tr("Checked"),
|
||||
tr("Shows icon indicators for emulation states such as Pausing, Turbo, Fast-Forward, and Slow-Motion."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showFrameTimes, tr("Show Frame Times"), tr("Unchecked"),
|
||||
tr("Displays a graph showing the average frametimes."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showHardwareInfo, tr("Show Hardware Info"), tr("Unchecked"),
|
||||
tr("Shows the current system CPU and GPU information."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showVersion, tr("Show PCSX2 Version"), tr("Unchecked"),
|
||||
tr("Shows the current PCSX2 version on the top-right corner of the display."));
|
||||
tr("Shows the current PCSX2 version."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showSettings, tr("Show Settings"), tr("Unchecked"),
|
||||
tr("Displays various settings and the current values of those settings in the bottom-right corner of the display."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showPatches, tr("Show Patches"), tr("Unchecked"),
|
||||
tr("Shows the amount of currently active patches/cheats in the bottom-right corner of the display."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showInputs, tr("Show Inputs"), tr("Unchecked"),
|
||||
tr("Shows the current controller state of the system in the bottom-left corner of the display."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showVideoCapture, tr("Show Video Capture Status"), tr("Checked"),
|
||||
tr("Shows the currently active video capture status."));
|
||||
tr("Shows the status of the currently active video capture in the top-right corner of the display.."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showInputRec, tr("Show Input Recording Status"), tr("Checked"),
|
||||
tr("Shows the currently active input recording status."));
|
||||
tr("Shows the status of the currently active input recording in the top-right corner of the display.."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.showHardwareInfo, tr("Show Hardware Info"), tr("Unchecked"),
|
||||
tr("Shows the current system hardware information on the OSD."));
|
||||
dialog()->registerWidgetHelp(m_osd.showTextureReplacements, tr("Show Texture Replacement Status"), tr("Checked"),
|
||||
tr("Shows the status of the number of dumped and loaded texture replacements in the top-right corner of the display."));
|
||||
|
||||
dialog()->registerWidgetHelp(m_osd.warnAboutUnsafeSettings, tr("Warn About Unsafe Settings"), tr("Checked"),
|
||||
tr("Displays warnings when settings are enabled which may break games."));
|
||||
@@ -943,16 +949,16 @@ void GraphicsSettingsWidget::onPerformancePosChanged()
|
||||
{
|
||||
const bool enabled = m_osd.performancePos->currentIndex() != (dialog()->isPerGameSettings() ? 1 : 0);
|
||||
|
||||
m_osd.showVPS->setEnabled(enabled);
|
||||
m_osd.showSpeed->setEnabled(enabled);
|
||||
m_osd.showSpeedPercentages->setEnabled(enabled);
|
||||
m_osd.showFPS->setEnabled(enabled);
|
||||
m_osd.showCPU->setEnabled(enabled);
|
||||
m_osd.showGPU->setEnabled(enabled);
|
||||
m_osd.showVPS->setEnabled(enabled);
|
||||
m_osd.showResolution->setEnabled(enabled);
|
||||
m_osd.showGSStats->setEnabled(enabled);
|
||||
m_osd.showHardwareInfo->setEnabled(enabled);
|
||||
m_osd.showIndicators->setEnabled(enabled);
|
||||
m_osd.showUsageCPU->setEnabled(enabled);
|
||||
m_osd.showUsageGPU->setEnabled(enabled);
|
||||
m_osd.showStatusIndicators->setEnabled(enabled);
|
||||
m_osd.showFrameTimes->setEnabled(enabled);
|
||||
m_osd.showHardwareInfo->setEnabled(enabled);
|
||||
m_osd.showVersion->setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* settings_dialog
|
||||
tr("Shows the game you are currently playing as part of your profile in Discord."));
|
||||
dialog()->registerWidgetHelp(
|
||||
m_ui.mouseLock, tr("Enable Mouse Lock"), tr("Unchecked"),
|
||||
tr("Locks the mouse cursor to the windows when PCSX2 is in focus and all other windows are closed.<br><b>Unavailable on Linux Wayland.</b><br><b>Requires accessibility permissions on macOS.</b><br><b>Limited support for mixed-resolution with non-100% DPI configurations.</b>"));
|
||||
tr("Locks the mouse cursor to the windows when PCSX2 is in focus and all other windows are closed.<br><b>Unavailable on Linux Wayland.</b><br><b>Requires accessibility permissions on macOS.</b>"));
|
||||
dialog()->registerWidgetHelp(
|
||||
m_ui.doubleClickTogglesFullscreen, tr("Double-Click Toggles Fullscreen"), tr("Checked"),
|
||||
tr("Allows switching in and out of fullscreen mode by double-clicking the game window."));
|
||||
|
||||
@@ -204,7 +204,7 @@ void SettingsWindow::setupUi(const GameList::Entry* game)
|
||||
tr("<strong>Advanced Settings</strong><hr>These are advanced options to determine the configuration of the simulated "
|
||||
"console.<br><br>Mouse over an option for additional information, and Shift+Wheel to scroll this panel."));
|
||||
addWidget(m_debug_settings = new DebugSettingsWidget(this, m_ui.settingsContainer), tr("Debug"),
|
||||
QStringLiteral("debugger-line"),
|
||||
QStringLiteral("bug-line"),
|
||||
tr("<strong>Debug Settings</strong><hr>These are options which can be used to log internal information about the application. "
|
||||
"<strong>Do not modify unless you know what you are doing</strong>, it will cause significant slowdown, and can waste large "
|
||||
"amounts of disk space."));
|
||||
|
||||
1
pcsx2-qt/resources/icons/black/svg/bug-line.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24"><path d="M13 19.9C15.2822 19.4367 17 17.419 17 15V12C17 11.299 16.8564 10.6219 16.5846 10H7.41538C7.14358 10.6219 7 11.299 7 12V15C7 17.419 8.71776 19.4367 11 19.9V14H13V19.9ZM5.5358 17.6907C5.19061 16.8623 5 15.9534 5 15H2V13H5V12C5 11.3573 5.08661 10.7348 5.2488 10.1436L3.0359 8.86602L4.0359 7.13397L6.05636 8.30049C6.11995 8.19854 6.18609 8.09835 6.25469 8H17.7453C17.8139 8.09835 17.88 8.19854 17.9436 8.30049L19.9641 7.13397L20.9641 8.86602L18.7512 10.1436C18.9134 10.7348 19 11.3573 19 12V13H22V15H19C19 15.9534 18.8094 16.8623 18.4642 17.6907L20.9641 19.134L19.9641 20.866L17.4383 19.4077C16.1549 20.9893 14.1955 22 12 22C9.80453 22 7.84512 20.9893 6.56171 19.4077L4.0359 20.866L3.0359 19.134L5.5358 17.6907ZM8 6C8 3.79086 9.79086 2 12 2C14.2091 2 16 3.79086 16 6H8Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 815 B |
@@ -1,28 +0,0 @@
|
||||
<svg viewBox="0 0 150 150">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke: #000;
|
||||
stroke-miterlimit: 10;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Camada_3">
|
||||
<g id="By_Maxihplay">
|
||||
<g id="baixo">
|
||||
<path class="cls-1" d="m20.57,127.29v-7.95h12.21v-30.79l-10.63,5.87-2.93-7.29,15.21-8.03h7.51v40.25h10.52v7.95h-31.89Z"/>
|
||||
<path class="cls-1" d="m95.6,103.13c0,3.94-.43,7.45-1.28,10.56-.86,3.1-2.11,5.73-3.76,7.86-1.65,2.14-3.66,3.77-6.03,4.89-2.37,1.12-5.08,1.69-8.14,1.69-2.64,0-5.07-.47-7.3-1.39-2.22-.93-4.14-2.39-5.76-4.38-1.61-1.99-2.87-4.54-3.78-7.64-.9-3.1-1.36-6.82-1.36-11.14,0-3.93.43-7.45,1.3-10.56.87-3.1,2.12-5.72,3.76-7.86,1.64-2.14,3.65-3.77,6.05-4.89,2.4-1.12,5.11-1.69,8.14-1.69,2.64,0,5.07.47,7.3,1.39,2.22.93,4.14,2.38,5.74,4.36,1.6,1.98,2.85,4.52,3.76,7.62.9,3.1,1.36,6.83,1.36,11.18Zm-28.37.15v1.37c0,.43.02.86.07,1.3l17.96-12.98c-.86-2.42-1.98-4.21-3.39-5.37s-3.06-1.74-4.97-1.74c-1.37,0-2.64.35-3.81,1.05s-2.19,1.77-3.06,3.21c-.87,1.44-1.55,3.25-2.05,5.43-.5,2.18-.75,4.75-.75,7.74Zm19.36.15c0-.42-.01-.84-.04-1.26-.02-.43-.04-.84-.04-1.23l-17.85,12.9c.78,2.37,1.88,4.13,3.3,5.28,1.42,1.15,3.07,1.72,4.95,1.72,1.37,0,2.64-.35,3.83-1.06s2.21-1.78,3.08-3.21c.87-1.43,1.55-3.24,2.03-5.43.49-2.19.73-4.76.73-7.72Z"/>
|
||||
<path class="cls-1" d="m103.12,127.29v-7.95h12.21v-30.79l-10.63,5.87-2.93-7.29,15.21-8.03h7.51v40.25h10.52v7.95h-31.89Z"/>
|
||||
</g>
|
||||
<g id="cima">
|
||||
<path class="cls-1" d="m52.38,46.43c0,3.94-.43,7.45-1.28,10.56-.86,3.1-2.11,5.73-3.76,7.86-1.65,2.14-3.66,3.77-6.03,4.89-2.37,1.12-5.08,1.69-8.14,1.69-2.64,0-5.07-.47-7.3-1.39-2.22-.93-4.14-2.39-5.76-4.38-1.61-1.99-2.87-4.54-3.78-7.64-.9-3.1-1.36-6.82-1.36-11.14,0-3.93.43-7.45,1.3-10.56.87-3.1,2.12-5.72,3.76-7.86,1.64-2.14,3.65-3.77,6.05-4.89,2.4-1.12,5.11-1.69,8.14-1.69,2.64,0,5.07.47,7.3,1.39,2.22.93,4.14,2.38,5.74,4.36,1.6,1.98,2.85,4.52,3.76,7.62.9,3.1,1.36,6.83,1.36,11.18Zm-28.37.15v1.37c0,.43.02.86.07,1.3l17.96-12.98c-.86-2.42-1.98-4.21-3.39-5.37s-3.06-1.74-4.97-1.74c-1.37,0-2.64.35-3.81,1.05s-2.19,1.77-3.06,3.21c-.87,1.44-1.55,3.25-2.05,5.43-.5,2.18-.75,4.75-.75,7.74Zm19.36.15c0-.42-.01-.84-.04-1.26-.02-.43-.04-.84-.04-1.23l-17.85,12.9c.78,2.37,1.88,4.13,3.3,5.28,1.42,1.15,3.07,1.72,4.95,1.72,1.37,0,2.64-.35,3.83-1.06s2.21-1.78,3.08-3.21c.87-1.43,1.55-3.24,2.03-5.43.49-2.19.73-4.76.73-7.72Z"/>
|
||||
<path class="cls-1" d="m59.89,70.58v-7.95h12.21v-30.79l-10.63,5.87-2.93-7.29,15.21-8.03h7.51v40.25h10.52v7.95h-31.89Z"/>
|
||||
<path class="cls-1" d="m134.93,46.43c0,3.94-.43,7.45-1.28,10.56-.86,3.1-2.11,5.73-3.76,7.86-1.65,2.14-3.66,3.77-6.03,4.89-2.37,1.12-5.08,1.69-8.14,1.69-2.64,0-5.07-.47-7.3-1.39-2.22-.93-4.14-2.39-5.76-4.38-1.61-1.99-2.87-4.54-3.78-7.64-.9-3.1-1.36-6.82-1.36-11.14,0-3.93.43-7.45,1.3-10.56.87-3.1,2.12-5.72,3.76-7.86,1.64-2.14,3.65-3.77,6.05-4.89,2.4-1.12,5.11-1.69,8.14-1.69,2.64,0,5.07.47,7.3,1.39,2.22.93,4.14,2.38,5.74,4.36,1.6,1.98,2.85,4.52,3.76,7.62.9,3.1,1.36,6.83,1.36,11.18Zm-28.37.15v1.37c0,.43.02.86.07,1.3l17.96-12.98c-.86-2.42-1.98-4.21-3.39-5.37-1.41-1.16-3.06-1.74-4.97-1.74-1.37,0-2.64.35-3.81,1.05s-2.19,1.77-3.06,3.21c-.87,1.44-1.55,3.25-2.05,5.43-.5,2.18-.75,4.75-.75,7.74Zm19.36.15c0-.42-.01-.84-.04-1.26-.02-.43-.04-.84-.04-1.23l-17.85,12.9c.78,2.37,1.88,4.13,3.3,5.28,1.42,1.15,3.07,1.72,4.95,1.72,1.37,0,2.64-.35,3.83-1.06s2.21-1.78,3.08-3.21c.87-1.43,1.55-3.24,2.03-5.43.49-2.19.73-4.76.73-7.72Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Camada_2">
|
||||
<path class="cls-2" d="m-3.8-.03h154.06v152.06H-3.8V-.03Z" fill="none"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -1,10 +0,0 @@
|
||||
<svg viewBox="0 0 512 512">
|
||||
<circle
|
||||
style="fill:none;stroke:#000000;stroke-width:39.1094;stroke-linecap:round;stroke-dasharray:none"
|
||||
cx="255.99998"
|
||||
cy="255.99998"
|
||||
r="236.44533"/>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:30;stroke-linecap:round"
|
||||
d="M 14.169739,256 H 138.21901 L 210.20476,131.31702 277.76735,383.464 358.15788,244.22352 h 139.38547"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 396 B |
1
pcsx2-qt/resources/icons/black/svg/lock-fill.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24"><path d="M19 10H20C20.5523 10 21 10.4477 21 11V21C21 21.5523 20.5523 22 20 22H4C3.44772 22 3 21.5523 3 21V11C3 10.4477 3.44772 10 4 10H5V9C5 5.13401 8.13401 2 12 2C15.866 2 19 5.13401 19 9V10ZM17 10V9C17 6.23858 14.7614 4 12 4C9.23858 4 7 6.23858 7 9V10H17ZM11 14V18H13V14H11Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 317 B |
1
pcsx2-qt/resources/icons/black/svg/lock-unlock-fill.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24"><path d="M7 10H20C20.5523 10 21 10.4477 21 11V21C21 21.5523 20.5523 22 20 22H4C3.44772 22 3 21.5523 3 21V11C3 10.4477 3.44772 10 4 10H5V9C5 5.13401 8.13401 2 12 2C14.7405 2 17.1131 3.5748 18.2624 5.86882L16.4731 6.76344C15.6522 5.12486 13.9575 4 12 4C9.23858 4 7 6.23858 7 9V10ZM10 15V17H14V15H10Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 338 B |
@@ -1 +0,0 @@
|
||||
<svg viewBox="0 0 512 512"><path d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg>
|
||||
|
Before Width: | Height: | Size: 391 B |
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="800px" height="800px" fill="none" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m8.1816 10.703s4e-5 -2.5676 0-4.1081c-4e-5 -1.8489 1.527-3.5946 3.8182-3.5946 2.2912 0 3.8181 1.7457 3.8181 3.5946v4.1081" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
<path d="m4.5 11.393c-4e-5 1.7387-1e-4 5.3708 2e-5 7.8056 1.3e-4 2.6923 4.1637 3.3012 7.5 3.3012 3.3363 0 7.4999-0.6089 7.4999-3.3012v-7.8056c0-0.5523-0.4477-0.9975-1-0.9975h-13c-0.55227 0-0.99998 0.4452-0.99999 0.9975zm6 4.6096c0 0.476 0.2069 0.9037 0.5357 1.198v1.5521c0 0.5522 0.4477 1 1 1h0.1429c0.5523 0 1-0.4478 1-1v-1.5521c0.3288-0.2943 0.5357-0.722 0.5357-1.198 0-0.8876-0.7195-1.6071-1.6071-1.6071-0.8877 0-1.6072 0.7195-1.6072 1.6071z" clip-rule="evenodd" fill="#000" fill-rule="evenodd"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 876 B |
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="800px" height="800px" fill="none" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m4.5 11.393c-4e-5 1.7387-1e-4 5.3708 2e-5 7.8056 1.3e-4 2.6923 4.1637 3.3012 7.5 3.3012 3.3363 0 7.4999-0.6089 7.4999-3.3012v-7.8056c0-0.5523-0.4477-0.9975-1-0.9975h-13c-0.55227 0-0.99998 0.4452-0.99999 0.9975zm6 4.6096c0 0.476 0.2069 0.9037 0.5357 1.198v1.5521c0 0.5522 0.4477 1 1 1h0.1429c0.5523 0 1-0.4478 1-1v-1.5521c0.3288-0.2943 0.5357-0.722 0.5357-1.198 0-0.8876-0.7195-1.6071-1.6071-1.6071-0.8877 0-1.6072 0.7195-1.6072 1.6071z" clip-rule="evenodd" fill="#000" fill-rule="evenodd"/>
|
||||
<path d="m8.1816 10.703s4e-5 -2.5676 0-4.1081c-4e-5 -1.8489 1.527-3.5946 3.8182-3.5946 2.2912 0 3.8181 1.7457 3.8181 3.5946" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 869 B |
1
pcsx2-qt/resources/icons/black/svg/search-line.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24"><path d="M18.031 16.6168L22.3137 20.8995L20.8995 22.3137L16.6168 18.031C15.0769 19.263 13.124 20 11 20C6.032 20 2 15.968 2 11C2 6.032 6.032 2 11 2C15.968 2 20 6.032 20 11C20 13.124 19.263 15.0769 18.031 16.6168ZM16.0247 15.8748C17.2475 14.6146 18 12.8956 18 11C18 7.1325 14.8675 4 11 4C7.1325 4 4 7.1325 4 11C4 14.8675 7.1325 18 11 18C12.8956 18 14.6146 17.2475 15.8748 16.0247L16.0247 15.8748Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 435 B |
1
pcsx2-qt/resources/icons/white/svg/bug-line.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" fill="#fff"><path d="M13 19.9C15.2822 19.4367 17 17.419 17 15V12C17 11.299 16.8564 10.6219 16.5846 10H7.41538C7.14358 10.6219 7 11.299 7 12V15C7 17.419 8.71776 19.4367 11 19.9V14H13V19.9ZM5.5358 17.6907C5.19061 16.8623 5 15.9534 5 15H2V13H5V12C5 11.3573 5.08661 10.7348 5.2488 10.1436L3.0359 8.86602L4.0359 7.13397L6.05636 8.30049C6.11995 8.19854 6.18609 8.09835 6.25469 8H17.7453C17.8139 8.09835 17.88 8.19854 17.9436 8.30049L19.9641 7.13397L20.9641 8.86602L18.7512 10.1436C18.9134 10.7348 19 11.3573 19 12V13H22V15H19C19 15.9534 18.8094 16.8623 18.4642 17.6907L20.9641 19.134L19.9641 20.866L17.4383 19.4077C16.1549 20.9893 14.1955 22 12 22C9.80453 22 7.84512 20.9893 6.56171 19.4077L4.0359 20.866L3.0359 19.134L5.5358 17.6907ZM8 6C8 3.79086 9.79086 2 12 2C14.2091 2 16 3.79086 16 6H8Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 827 B |
@@ -1,31 +0,0 @@
|
||||
<svg viewBox="0 0 150 150">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #fff;
|
||||
stroke: #fff;
|
||||
stroke-miterlimit: 10;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Camada_3">
|
||||
<g id="codigos">
|
||||
<g id="By_Maxihplay">
|
||||
<g id="baixo">
|
||||
<path class="cls-1" d="m20.57,127.29v-7.95h12.21v-30.79l-10.63,5.87-2.93-7.29,15.21-8.03h7.51v40.25h10.52v7.95h-31.89Z"/>
|
||||
<path class="cls-1" d="m95.6,103.13c0,3.94-.43,7.45-1.28,10.56-.86,3.1-2.11,5.73-3.76,7.86-1.65,2.14-3.66,3.77-6.03,4.89-2.37,1.12-5.08,1.69-8.14,1.69-2.64,0-5.07-.47-7.3-1.39-2.22-.93-4.14-2.39-5.76-4.38-1.61-1.99-2.87-4.54-3.78-7.64-.9-3.1-1.36-6.82-1.36-11.14,0-3.93.43-7.45,1.3-10.56.87-3.1,2.12-5.72,3.76-7.86,1.64-2.14,3.65-3.77,6.05-4.89,2.4-1.12,5.11-1.69,8.14-1.69,2.64,0,5.07.47,7.3,1.39,2.22.93,4.14,2.38,5.74,4.36,1.6,1.98,2.85,4.52,3.76,7.62.9,3.1,1.36,6.83,1.36,11.18Zm-28.37.15v1.37c0,.43.02.86.07,1.3l17.96-12.98c-.86-2.42-1.98-4.21-3.39-5.37s-3.06-1.74-4.97-1.74c-1.37,0-2.64.35-3.81,1.05s-2.19,1.77-3.06,3.21c-.87,1.44-1.55,3.25-2.05,5.43-.5,2.18-.75,4.75-.75,7.74Zm19.36.15c0-.42-.01-.84-.04-1.26-.02-.43-.04-.84-.04-1.23l-17.85,12.9c.78,2.37,1.88,4.13,3.3,5.28,1.42,1.15,3.07,1.72,4.95,1.72,1.37,0,2.64-.35,3.83-1.06s2.21-1.78,3.08-3.21c.87-1.43,1.55-3.24,2.03-5.43.49-2.19.73-4.76.73-7.72Z"/>
|
||||
<path class="cls-1" d="m103.12,127.29v-7.95h12.21v-30.79l-10.63,5.87-2.93-7.29,15.21-8.03h7.51v40.25h10.52v7.95h-31.89Z"/>
|
||||
</g>
|
||||
<g id="cima">
|
||||
<path class="cls-1" d="m52.38,46.43c0,3.94-.43,7.45-1.28,10.56-.86,3.1-2.11,5.73-3.76,7.86-1.65,2.14-3.66,3.77-6.03,4.89-2.37,1.12-5.08,1.69-8.14,1.69-2.64,0-5.07-.47-7.3-1.39-2.22-.93-4.14-2.39-5.76-4.38-1.61-1.99-2.87-4.54-3.78-7.64-.9-3.1-1.36-6.82-1.36-11.14,0-3.93.43-7.45,1.3-10.56.87-3.1,2.12-5.72,3.76-7.86,1.64-2.14,3.65-3.77,6.05-4.89,2.4-1.12,5.11-1.69,8.14-1.69,2.64,0,5.07.47,7.3,1.39,2.22.93,4.14,2.38,5.74,4.36,1.6,1.98,2.85,4.52,3.76,7.62.9,3.1,1.36,6.83,1.36,11.18Zm-28.37.15v1.37c0,.43.02.86.07,1.3l17.96-12.98c-.86-2.42-1.98-4.21-3.39-5.37s-3.06-1.74-4.97-1.74c-1.37,0-2.64.35-3.81,1.05s-2.19,1.77-3.06,3.21c-.87,1.44-1.55,3.25-2.05,5.43-.5,2.18-.75,4.75-.75,7.74Zm19.36.15c0-.42-.01-.84-.04-1.26-.02-.43-.04-.84-.04-1.23l-17.85,12.9c.78,2.37,1.88,4.13,3.3,5.28,1.42,1.15,3.07,1.72,4.95,1.72,1.37,0,2.64-.35,3.83-1.06s2.21-1.78,3.08-3.21c.87-1.43,1.55-3.24,2.03-5.43.49-2.19.73-4.76.73-7.72Z"/>
|
||||
<path class="cls-1" d="m59.89,70.58v-7.95h12.21v-30.79l-10.63,5.87-2.93-7.29,15.21-8.03h7.51v40.25h10.52v7.95h-31.89Z"/>
|
||||
<path class="cls-1" d="m134.93,46.43c0,3.94-.43,7.45-1.28,10.56-.86,3.1-2.11,5.73-3.76,7.86-1.65,2.14-3.66,3.77-6.03,4.89-2.37,1.12-5.08,1.69-8.14,1.69-2.64,0-5.07-.47-7.3-1.39-2.22-.93-4.14-2.39-5.76-4.38-1.61-1.99-2.87-4.54-3.78-7.64-.9-3.1-1.36-6.82-1.36-11.14,0-3.93.43-7.45,1.3-10.56.87-3.1,2.12-5.72,3.76-7.86,1.64-2.14,3.65-3.77,6.05-4.89,2.4-1.12,5.11-1.69,8.14-1.69,2.64,0,5.07.47,7.3,1.39,2.22.93,4.14,2.38,5.74,4.36,1.6,1.98,2.85,4.52,3.76,7.62.9,3.1,1.36,6.83,1.36,11.18Zm-28.37.15v1.37c0,.43.02.86.07,1.3l17.96-12.98c-.86-2.42-1.98-4.21-3.39-5.37-1.41-1.16-3.06-1.74-4.97-1.74-1.37,0-2.64.35-3.81,1.05s-2.19,1.77-3.06,3.21c-.87,1.44-1.55,3.25-2.05,5.43-.5,2.18-.75,4.75-.75,7.74Zm19.36.15c0-.42-.01-.84-.04-1.26-.02-.43-.04-.84-.04-1.23l-17.85,12.9c.78,2.37,1.88,4.13,3.3,5.28,1.42,1.15,3.07,1.72,4.95,1.72,1.37,0,2.64-.35,3.83-1.06,1.19-.71,2.21-1.78,3.08-3.21.87-1.43,1.55-3.24,2.03-5.43.49-2.19.73-4.76.73-7.72Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Camada_2">
|
||||
<path class="cls-2" d="m-3.8-.03h154.06v152.06H-3.8V-.03Z" fill="none"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,10 +0,0 @@
|
||||
<svg viewBox="0 0 512 512">
|
||||
<circle
|
||||
style="fill:none;stroke:#ffffff;stroke-width:39.1094;stroke-linecap:round;stroke-dasharray:none"
|
||||
cx="255.99998"
|
||||
cy="255.99998"
|
||||
r="236.44533" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:30;stroke-linecap:round"
|
||||
d="M 14.169739,256 H 138.21901 L 210.20476,131.31702 277.76735,383.464 358.15788,244.22352 h 139.38547"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 397 B |
1
pcsx2-qt/resources/icons/white/svg/lock-fill.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" fill="#fff"><path d="M19 10H20C20.5523 10 21 10.4477 21 11V21C21 21.5523 20.5523 22 20 22H4C3.44772 22 3 21.5523 3 21V11C3 10.4477 3.44772 10 4 10H5V9C5 5.13401 8.13401 2 12 2C15.866 2 19 5.13401 19 9V10ZM17 10V9C17 6.23858 14.7614 4 12 4C9.23858 4 7 6.23858 7 9V10H17ZM11 14V18H13V14H11Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 329 B |
1
pcsx2-qt/resources/icons/white/svg/lock-unlock-fill.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" fill="#fff"><path d="M7 10H20C20.5523 10 21 10.4477 21 11V21C21 21.5523 20.5523 22 20 22H4C3.44772 22 3 21.5523 3 21V11C3 10.4477 3.44772 10 4 10H5V9C5 5.13401 8.13401 2 12 2C14.7405 2 17.1131 3.5748 18.2624 5.86882L16.4731 6.76344C15.6522 5.12486 13.9575 4 12 4C9.23858 4 7 6.23858 7 9V10ZM10 15V17H14V15H10Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 350 B |
1
pcsx2-qt/resources/icons/white/svg/search-line.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" fill="#fff"><path d="M18.031 16.6168L22.3137 20.8995L20.8995 22.3137L16.6168 18.031C15.0769 19.263 13.124 20 11 20C6.032 20 2 15.968 2 11C2 6.032 6.032 2 11 2C15.968 2 20 6.032 20 11C20 13.124 19.263 15.0769 18.031 16.6168ZM16.0247 15.8748C17.2475 14.6146 18 12.8956 18 11C18 7.1325 14.8675 4 11 4C7.1325 4 4 7.1325 4 11C4 14.8675 7.1325 18 11 18C12.8956 18 14.6146 17.2475 15.8748 16.0247L16.0247 15.8748Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 447 B |
@@ -9,6 +9,7 @@
|
||||
<file>icons/black/svg/booklet.svg</file>
|
||||
<file>icons/black/svg/book.svg</file>
|
||||
<file>icons/black/svg/brush-line.svg</file>
|
||||
<file>icons/black/svg/bug-line.svg</file>
|
||||
<file>icons/black/svg/buzz-controller-line.svg</file>
|
||||
<file>icons/black/svg/camera-video.svg</file>
|
||||
<file>icons/black/svg/cheats-line.svg</file>
|
||||
@@ -17,7 +18,6 @@
|
||||
<file>icons/black/svg/close-line.svg</file>
|
||||
<file>icons/black/svg/controller-line.svg</file>
|
||||
<file>icons/black/svg/controller-strike-line.svg</file>
|
||||
<file>icons/black/svg/debugger-line.svg</file>
|
||||
<file>icons/black/svg/debug-step-into-line.svg</file>
|
||||
<file>icons/black/svg/debug-step-out-line.svg</file>
|
||||
<file>icons/black/svg/debug-step-over-line.svg</file>
|
||||
@@ -54,7 +54,6 @@
|
||||
<file>icons/black/svg/guitar-line.svg</file>
|
||||
<file>icons/black/svg/guncon2-line.svg</file>
|
||||
<file>icons/black/svg/headset-line.svg</file>
|
||||
<file>icons/black/svg/heart-circle-line.svg</file>
|
||||
<file>icons/black/svg/image-fill.svg</file>
|
||||
<file>icons/black/svg/interface-line.svg</file>
|
||||
<file>icons/black/svg/jogcon-line.svg</file>
|
||||
@@ -63,16 +62,15 @@
|
||||
<file>icons/black/svg/keyboardmania-line.svg</file>
|
||||
<file>icons/black/svg/lightbulb-line.svg</file>
|
||||
<file>icons/black/svg/list-check.svg</file>
|
||||
<file>icons/black/svg/lock-fill.svg</file>
|
||||
<file>icons/black/svg/lock-unlock-fill.svg</file>
|
||||
<file>icons/black/svg/login-box-line.svg</file>
|
||||
<file>icons/black/svg/magnifier-line.svg</file>
|
||||
<file>icons/black/svg/memcard-line.svg</file>
|
||||
<file>icons/black/svg/mic-line.svg</file>
|
||||
<file>icons/black/svg/minus-line.svg</file>
|
||||
<file>icons/black/svg/mouse-line.svg</file>
|
||||
<file>icons/black/svg/msd-line.svg</file>
|
||||
<file>icons/black/svg/negcon-line.svg</file>
|
||||
<file>icons/black/svg/padlock-lock.svg</file>
|
||||
<file>icons/black/svg/padlock-unlock.svg</file>
|
||||
<file>icons/black/svg/pause-line.svg</file>
|
||||
<file>icons/black/svg/pencil-line.svg</file>
|
||||
<file>icons/black/svg/pin-filled.svg</file>
|
||||
@@ -87,6 +85,7 @@
|
||||
<file>icons/black/svg/save-3-line.svg</file>
|
||||
<file>icons/black/svg/screenshot-2-line.svg</file>
|
||||
<file>icons/black/svg/seamic-line.svg</file>
|
||||
<file>icons/black/svg/search-line.svg</file>
|
||||
<file>icons/black/svg/settings-3-line.svg</file>
|
||||
<file>icons/black/svg/shut-down-line.svg</file>
|
||||
<file>icons/black/svg/singstar-line.svg</file>
|
||||
@@ -114,6 +113,7 @@
|
||||
<file>icons/white/svg/booklet.svg</file>
|
||||
<file>icons/white/svg/book.svg</file>
|
||||
<file>icons/white/svg/brush-line.svg</file>
|
||||
<file>icons/white/svg/bug-line.svg</file>
|
||||
<file>icons/white/svg/buzz-controller-line.svg</file>
|
||||
<file>icons/white/svg/camera-video.svg</file>
|
||||
<file>icons/white/svg/cheats-line.svg</file>
|
||||
@@ -122,7 +122,6 @@
|
||||
<file>icons/white/svg/close-line.svg</file>
|
||||
<file>icons/white/svg/controller-line.svg</file>
|
||||
<file>icons/white/svg/controller-strike-line.svg</file>
|
||||
<file>icons/white/svg/debugger-line.svg</file>
|
||||
<file>icons/white/svg/debug-step-into-line.svg</file>
|
||||
<file>icons/white/svg/debug-step-out-line.svg</file>
|
||||
<file>icons/white/svg/debug-step-over-line.svg</file>
|
||||
@@ -159,7 +158,6 @@
|
||||
<file>icons/white/svg/guitar-line.svg</file>
|
||||
<file>icons/white/svg/guncon2-line.svg</file>
|
||||
<file>icons/white/svg/headset-line.svg</file>
|
||||
<file>icons/white/svg/heart-circle-line.svg</file>
|
||||
<file>icons/white/svg/image-fill.svg</file>
|
||||
<file>icons/white/svg/interface-line.svg</file>
|
||||
<file>icons/white/svg/jogcon-line.svg</file>
|
||||
@@ -168,6 +166,8 @@
|
||||
<file>icons/white/svg/keyboardmania-line.svg</file>
|
||||
<file>icons/white/svg/lightbulb-line.svg</file>
|
||||
<file>icons/white/svg/list-check.svg</file>
|
||||
<file>icons/white/svg/lock-fill.svg</file>
|
||||
<file>icons/white/svg/lock-unlock-fill.svg</file>
|
||||
<file>icons/white/svg/login-box-line.svg</file>
|
||||
<file>icons/white/svg/magnifier-line.svg</file>
|
||||
<file>icons/white/svg/memcard-line.svg</file>
|
||||
@@ -192,6 +192,7 @@
|
||||
<file>icons/white/svg/save-3-line.svg</file>
|
||||
<file>icons/white/svg/screenshot-2-line.svg</file>
|
||||
<file>icons/white/svg/seamic-line.svg</file>
|
||||
<file>icons/white/svg/search-line.svg</file>
|
||||
<file>icons/white/svg/settings-3-line.svg</file>
|
||||
<file>icons/white/svg/shut-down-line.svg</file>
|
||||
<file>icons/white/svg/singstar-line.svg</file>
|
||||
|
||||
@@ -736,19 +736,20 @@ struct Pcsx2Config
|
||||
OsdShowSpeed : 1,
|
||||
OsdShowFPS : 1,
|
||||
OsdShowVPS : 1,
|
||||
OsdShowCPU : 1,
|
||||
OsdShowGPU : 1,
|
||||
OsdShowResolution : 1,
|
||||
OsdShowGSStats : 1,
|
||||
OsdShowCPU : 1,
|
||||
OsdShowGPU : 1,
|
||||
OsdShowIndicators : 1,
|
||||
OsdShowFrameTimes : 1,
|
||||
OsdShowHardwareInfo : 1,
|
||||
OsdShowVersion : 1,
|
||||
OsdShowSettings : 1,
|
||||
OsdshowPatches : 1,
|
||||
OsdShowInputs : 1,
|
||||
OsdShowFrameTimes : 1,
|
||||
OsdShowVersion : 1,
|
||||
OsdShowVideoCapture : 1,
|
||||
OsdShowInputRec : 1,
|
||||
OsdShowHardwareInfo : 1,
|
||||
OsdShowTextureReplacements : 1,
|
||||
HWSpinGPUForReadbacks : 1,
|
||||
HWSpinCPUForReadbacks : 1,
|
||||
GPUPaletteConversion : 1,
|
||||
|
||||
@@ -252,7 +252,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
|
||||
const u64 accumilatedHRenderError = (hRender % 10000) + (hBlank % 10000);
|
||||
const u64 accumilatedHFractional = accumilatedHRenderError % 10000;
|
||||
info->hRender += (u32)(accumilatedHRenderError / 10000);
|
||||
info->hSyncError = (accumilatedHFractional * (scansPerFrame / (IsInterlacedVideoMode() ? 2 : 1))) / 10000;
|
||||
info->hSyncError = (u32)((accumilatedHFractional * (scansPerFrame / (IsInterlacedVideoMode() ? 2 : 1))) / 10000);
|
||||
|
||||
// Note: In NTSC modes there is some small rounding error in the vsync too,
|
||||
// however it would take thousands of frames for it to amount to anything and
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace InternalServers
|
||||
//Counts
|
||||
ret->questions = dns.questions;
|
||||
|
||||
DNS_State* state = new DNS_State(reqs.size(), reqs, ret, payload->sourcePort);
|
||||
DNS_State* state = new DNS_State(static_cast<int>(reqs.size()), reqs, ret, payload->sourcePort);
|
||||
outstandingQueries++;
|
||||
|
||||
for (size_t i = 0; i < reqs.size(); i++)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/ScopedGuard.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#elif defined(__POSIX__)
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "sockets.h"
|
||||
#include "AdapterUtils.h"
|
||||
#include "DEV9.h"
|
||||
#include "Host.h"
|
||||
|
||||
#include "Sessions/ICMP_Session/ICMP_Session.h"
|
||||
#include "Sessions/TCP_Session/TCP_Session.h"
|
||||
@@ -45,7 +47,7 @@ std::vector<AdapterEntry> SocketAdapter::GetAdapters()
|
||||
std::vector<AdapterEntry> nic;
|
||||
AdapterEntry autoEntry;
|
||||
autoEntry.type = Pcsx2Config::DEV9Options::NetApi::Sockets;
|
||||
autoEntry.name = "Auto";
|
||||
autoEntry.name = TRANSLATE_STR("DEV9", "Auto");
|
||||
autoEntry.guid = "Auto";
|
||||
nic.push_back(autoEntry);
|
||||
|
||||
|
||||
@@ -8,22 +8,19 @@
|
||||
|
||||
std::vector<std::unique_ptr<BiosThread>> getEEThreads()
|
||||
{
|
||||
std::vector<std::unique_ptr<BiosThread>> threads;
|
||||
|
||||
if (CurrentBiosInformation.eeThreadListAddr <= 0)
|
||||
return threads;
|
||||
if (!VMManager::HasValidVM() || CurrentBiosInformation.eeThreadListAddr == 0)
|
||||
return {};
|
||||
|
||||
const u32 start = CurrentBiosInformation.eeThreadListAddr & 0x3fffff;
|
||||
|
||||
std::vector<std::unique_ptr<BiosThread>> threads;
|
||||
for (int tid = 0; tid < 256; tid++)
|
||||
{
|
||||
EEInternalThread* internal = static_cast<EEInternalThread*>(
|
||||
PSM(start + tid * sizeof(EEInternalThread)));
|
||||
|
||||
EEInternalThread* internal = static_cast<EEInternalThread*>(PSM(start + tid * sizeof(EEInternalThread)));
|
||||
if (internal->status != (int)ThreadStatus::THS_BAD)
|
||||
{
|
||||
auto thread = std::make_unique<EEThread>(tid, *internal);
|
||||
threads.push_back(std::move(thread));
|
||||
}
|
||||
if (internal && internal->status != (int)ThreadStatus::THS_BAD)
|
||||
threads.emplace_back(std::make_unique<EEThread>(tid, *internal));
|
||||
}
|
||||
|
||||
return threads;
|
||||
@@ -63,8 +60,7 @@ std::vector<std::unique_ptr<BiosThread>> getIOPThreads()
|
||||
|
||||
data.PC = iopMemRead32(data.SavedSP + 0x8c);
|
||||
|
||||
auto thread = std::make_unique<IOPThread>(data);
|
||||
threads.push_back(std::move(thread));
|
||||
threads.emplace_back(std::make_unique<IOPThread>(data));
|
||||
|
||||
item = iopMemRead32(item + 0x24);
|
||||
}
|
||||
@@ -93,7 +89,7 @@ std::vector<IopMod> getIOPModules()
|
||||
if (i > 1000)
|
||||
return {};
|
||||
|
||||
IopMod mod;
|
||||
IopMod& mod = modlist.emplace_back();
|
||||
|
||||
u32 nstr = iopMemRead32(maddr + 4);
|
||||
if (nstr)
|
||||
@@ -113,8 +109,6 @@ std::vector<IopMod> getIOPModules()
|
||||
mod.data_size = iopMemRead32(maddr + 0x20);
|
||||
mod.bss_size = iopMemRead32(maddr + 0x24);
|
||||
|
||||
modlist.push_back(mod);
|
||||
|
||||
maddr = iopMemRead32(maddr);
|
||||
}
|
||||
|
||||
|
||||
@@ -186,9 +186,7 @@ namespace MIPSAnalyst
|
||||
bool suspectedNoReturn = false;
|
||||
|
||||
u32 addr;
|
||||
for (u64 i = startAddr; i <= endAddr; i += 4) {
|
||||
addr = static_cast<u32>(i);
|
||||
|
||||
for (addr = startAddr; addr < endAddr; addr += 4) {
|
||||
// Use pre-existing symbol map info if available. May be more reliable.
|
||||
ccc::FunctionHandle existing_symbol_handle = database.functions.first_handle_from_starting_address(addr);
|
||||
const ccc::Function* existing_symbol = database.functions.symbol_from_handle(existing_symbol_handle);
|
||||
|
||||
@@ -674,11 +674,11 @@ void GSgetStats(SmallStringBase& info)
|
||||
}
|
||||
else if (pps >= _1kb)
|
||||
{
|
||||
pps /= _1kb; // Kpps
|
||||
prefix = 'K';
|
||||
pps /= _1kb; // kpps
|
||||
prefix = 'k';
|
||||
}
|
||||
|
||||
info.format("{} SW | {} SP | {} P | {} D | {:.2f} S | {:.2f} U | {:.2f} {}pps",
|
||||
info.format("{} SW | {} SYNP | {} PRIM | {} DRW | {:.2f} SWIZ | {:.2f} UNSWIZ | {:.2f} {}pps",
|
||||
api_name,
|
||||
(int)pm.Get(GSPerfMon::SyncPoint),
|
||||
(int)pm.Get(GSPerfMon::Prim),
|
||||
@@ -693,7 +693,7 @@ void GSgetStats(SmallStringBase& info)
|
||||
}
|
||||
else
|
||||
{
|
||||
info.format("{} HW | {} P | {} D | {} DC | {} B | {} RP | {} RB | {} TC | {} TU",
|
||||
info.format("{} HW | {} PRIM | {} DRW | {} DRWC | {} BAR | {} RP | {} RB | {} TC | {} TU",
|
||||
api_name,
|
||||
(int)pm.Get(GSPerfMon::Prim),
|
||||
(int)pm.Get(GSPerfMon::Draw),
|
||||
@@ -733,7 +733,7 @@ void GSgetMemoryStats(SmallStringBase& info)
|
||||
{
|
||||
const double hashcache_MB = get_MB(static_cast<double>(g_texture_cache->GetHashCacheMemoryUsage()));
|
||||
const double total_MB = targets_MB + sources_MB + hashcache_MB + pool_MB;
|
||||
info.format("VRAM: {} MB | T: {} MB | S: {} MB | H: {} MB | P: {} MB",
|
||||
info.format("VRAM: {} MB | TGT: {} MB | SRC: {} MB | HC: {} MB | PL: {} MB",
|
||||
format_precision(total_MB),
|
||||
format_precision(targets_MB),
|
||||
format_precision(sources_MB),
|
||||
@@ -743,7 +743,7 @@ void GSgetMemoryStats(SmallStringBase& info)
|
||||
else
|
||||
{
|
||||
const double total_MB = targets_MB + sources_MB + pool_MB;
|
||||
info.format("VRAM: {} MB | T: {} MB | S: {} MB | P: {} MB",
|
||||
info.format("VRAM: {} MB | TGT: {} MB | SRC: {} MB | PL: {} MB",
|
||||
format_precision(total_MB),
|
||||
format_precision(targets_MB),
|
||||
format_precision(sources_MB),
|
||||
@@ -1134,6 +1134,7 @@ static void HotkeyToggleOSD()
|
||||
GSConfig.OsdShowInputs ^= EmuConfig.GS.OsdShowInputs;
|
||||
GSConfig.OsdShowInputRec ^= EmuConfig.GS.OsdShowInputRec;
|
||||
GSConfig.OsdShowVideoCapture ^= EmuConfig.GS.OsdShowVideoCapture;
|
||||
GSConfig.OsdShowTextureReplacements ^= EmuConfig.GS.OsdShowTextureReplacements;
|
||||
|
||||
GSConfig.OsdMessagesPos =
|
||||
GSConfig.OsdMessagesPos == OsdOverlayPos::None ? EmuConfig.GS.OsdMessagesPos : OsdOverlayPos::None;
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
protected:
|
||||
double m_counters[CounterLast] = {};
|
||||
double m_stats[CounterLast] = {};
|
||||
u64 m_frame = 0;
|
||||
int m_frame = 0;
|
||||
clock_t m_lastframe = 0;
|
||||
int m_count = 0;
|
||||
int m_disp_fb_sprite_blits = 0;
|
||||
@@ -46,8 +46,8 @@ public:
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetFrame(u64 frame) { m_frame = frame; }
|
||||
u64 GetFrame() { return m_frame; }
|
||||
void SetFrame(int frame) { m_frame = frame; }
|
||||
int GetFrame() { return m_frame; }
|
||||
void EndFrame(bool frame_only);
|
||||
|
||||
void Put(counter_t c, double val) { m_counters[c] += val; }
|
||||
@@ -68,4 +68,4 @@ public:
|
||||
void Dump(const std::string& filename, bool hw);
|
||||
};
|
||||
|
||||
extern GSPerfMon g_perfmon;
|
||||
extern GSPerfMon g_perfmon;
|
||||
|
||||
@@ -1077,7 +1077,7 @@ __forceinline void GSState::ApplyPRIM(u32 prim)
|
||||
else
|
||||
m_env.PRIM.PRIM = prim & 0x7;
|
||||
|
||||
if (m_prev_env.PRIM.U32[0] ^ m_env.PRIM.U32[0])
|
||||
if ((m_prev_env.PRIM.U32[0] ^ m_env.PRIM.U32[0]) & PRIM_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_PRIM);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1<< DIRTY_REG_PRIM);
|
||||
@@ -1335,7 +1335,7 @@ void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].MIPTBP1.U64 ^ mip_tbp1.U64)
|
||||
if ((m_prev_env.CTXT[i].MIPTBP1.U64 ^ mip_tbp1.U64) & MIPTBP_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_MIPTBP1);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_MIPTBP1);
|
||||
@@ -1354,7 +1354,7 @@ void GSState::GIFRegHandlerCLAMP(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].CLAMP.U64 ^ m_env.CTXT[i].CLAMP.U64)
|
||||
if ((m_prev_env.CTXT[i].CLAMP.U64 ^ m_env.CTXT[i].CLAMP.U64) & CLAMP_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_CLAMP);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_CLAMP);
|
||||
@@ -1379,7 +1379,7 @@ void GSState::GIFRegHandlerTEX1(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].TEX1.U64 ^ m_env.CTXT[i].TEX1.U64)
|
||||
if ((m_prev_env.CTXT[i].TEX1.U64 ^ m_env.CTXT[i].TEX1.U64) & TEX1_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_TEX1);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_TEX1);
|
||||
@@ -1411,11 +1411,11 @@ void GSState::GIFRegHandlerXYOFFSET(const GIFReg* RESTRICT r)
|
||||
{
|
||||
GL_REG("XYOFFSET_%d = 0x%x_%x", i, r->U32[1], r->U32[0]);
|
||||
|
||||
const u64 r_masked = r->U64 & 0x0000FFFF0000FFFFu;
|
||||
const u64 r_masked = r->U64 & XYOFFSET_REG_MASK;
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].XYOFFSET.U64 != r_masked)
|
||||
if ((m_prev_env.CTXT[i].XYOFFSET.U64 ^ r_masked) & XYOFFSET_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_XYOFFSET);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_XYOFFSET);
|
||||
@@ -1450,7 +1450,7 @@ void GSState::GIFRegHandlerPRMODE(const GIFReg* RESTRICT r)
|
||||
m_env.PRIM = r->PRMODE;
|
||||
m_env.PRIM.PRIM = _PRIM;
|
||||
|
||||
if (m_prev_env.PRIM.U32[0] ^ m_env.PRIM.U32[0])
|
||||
if ((m_prev_env.PRIM.U32[0] ^ m_env.PRIM.U32[0]) & PRIM_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_PRIM);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_PRIM);
|
||||
@@ -1487,7 +1487,7 @@ void GSState::GIFRegHandlerMIPTBP1(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].MIPTBP1.U64 != m_env.CTXT[i].MIPTBP1.U64)
|
||||
if ((m_prev_env.CTXT[i].MIPTBP1.U64 ^ m_env.CTXT[i].MIPTBP1.U64) & MIPTBP_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_MIPTBP1);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_MIPTBP1);
|
||||
@@ -1503,7 +1503,7 @@ void GSState::GIFRegHandlerMIPTBP2(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].MIPTBP2.U64 != m_env.CTXT[i].MIPTBP2.U64)
|
||||
if ((m_prev_env.CTXT[i].MIPTBP2.U64 ^ m_env.CTXT[i].MIPTBP2.U64) & MIPTBP_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_MIPTBP2);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_MIPTBP2);
|
||||
@@ -1516,7 +1516,7 @@ void GSState::GIFRegHandlerTEXA(const GIFReg* RESTRICT r)
|
||||
|
||||
m_env.TEXA = r->TEXA;
|
||||
|
||||
if (m_prev_env.TEXA != m_env.TEXA)
|
||||
if ((m_prev_env.TEXA.U64 ^ m_env.TEXA.U64) & TEXA_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_TEXA);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_TEXA);
|
||||
@@ -1528,7 +1528,7 @@ void GSState::GIFRegHandlerFOGCOL(const GIFReg* RESTRICT r)
|
||||
|
||||
m_env.FOGCOL = r->FOGCOL;
|
||||
|
||||
if (m_prev_env.FOGCOL != m_env.FOGCOL)
|
||||
if ((m_prev_env.FOGCOL.U32[0] ^ m_env.FOGCOL.U32[0]) & FOGCOL_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_FOGCOL);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_FOGCOL);
|
||||
@@ -1548,7 +1548,7 @@ void GSState::GIFRegHandlerSCISSOR(const GIFReg* RESTRICT r)
|
||||
{
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].SCISSOR.U64 != r->SCISSOR.U64)
|
||||
if ((m_prev_env.CTXT[i].SCISSOR.U64 ^ r->SCISSOR.U64) & SCISSOR_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_SCISSOR);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_SCISSOR);
|
||||
@@ -1579,7 +1579,7 @@ void GSState::GIFRegHandlerALPHA(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].ALPHA.U64 != m_env.CTXT[i].ALPHA.U64)
|
||||
if ((m_prev_env.CTXT[i].ALPHA.U64 ^ m_env.CTXT[i].ALPHA.U64) & ALPHA_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_ALPHA);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_ALPHA);
|
||||
@@ -1590,7 +1590,7 @@ void GSState::GIFRegHandlerDIMX(const GIFReg* RESTRICT r)
|
||||
{
|
||||
m_env.DIMX = r->DIMX;
|
||||
|
||||
if (m_prev_env.DIMX != m_env.DIMX)
|
||||
if ((m_prev_env.DIMX.U64 ^ m_env.DIMX.U64) & DIMX_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_DIMX);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_DIMX);
|
||||
@@ -1600,7 +1600,7 @@ void GSState::GIFRegHandlerDTHE(const GIFReg* RESTRICT r)
|
||||
{
|
||||
m_env.DTHE = r->DTHE;
|
||||
|
||||
if (m_prev_env.DTHE != m_env.DTHE)
|
||||
if (m_prev_env.DTHE.DTHE != m_env.DTHE.DTHE)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_DTHE);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_DTHE);
|
||||
@@ -1610,7 +1610,7 @@ void GSState::GIFRegHandlerCOLCLAMP(const GIFReg* RESTRICT r)
|
||||
{
|
||||
m_env.COLCLAMP = r->COLCLAMP;
|
||||
|
||||
if (m_prev_env.COLCLAMP != m_env.COLCLAMP)
|
||||
if (m_prev_env.COLCLAMP.CLAMP != m_env.COLCLAMP.CLAMP)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_COLCLAMP);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_COLCLAMP);
|
||||
@@ -1623,7 +1623,7 @@ void GSState::GIFRegHandlerTEST(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].TEST != m_env.CTXT[i].TEST)
|
||||
if ((m_prev_env.CTXT[i].TEST.U32[0] ^ m_env.CTXT[i].TEST.U32[0]) & TEST_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_TEST);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_TEST);
|
||||
@@ -1634,7 +1634,7 @@ void GSState::GIFRegHandlerPABE(const GIFReg* RESTRICT r)
|
||||
{
|
||||
m_env.PABE = r->PABE;
|
||||
|
||||
if (m_prev_env.PABE != m_env.PABE)
|
||||
if (m_prev_env.PABE.PABE != m_env.PABE.PABE)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_PABE);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_PABE);
|
||||
@@ -1647,7 +1647,7 @@ void GSState::GIFRegHandlerFBA(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].FBA != m_env.CTXT[i].FBA)
|
||||
if (m_prev_env.CTXT[i].FBA.FBA != m_env.CTXT[i].FBA.FBA)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_FBA);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_FBA);
|
||||
@@ -1701,7 +1701,7 @@ void GSState::GIFRegHandlerFRAME(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].FRAME != m_env.CTXT[i].FRAME)
|
||||
if ((m_prev_env.CTXT[i].FRAME.U64 ^ m_env.CTXT[i].FRAME.U64) & FRAME_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_FRAME);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_FRAME);
|
||||
@@ -1736,7 +1736,7 @@ void GSState::GIFRegHandlerZBUF(const GIFReg* RESTRICT r)
|
||||
|
||||
if (i == m_prev_env.PRIM.CTXT)
|
||||
{
|
||||
if (m_prev_env.CTXT[i].ZBUF != m_env.CTXT[i].ZBUF)
|
||||
if ((m_prev_env.CTXT[i].ZBUF.U64 ^ m_env.CTXT[i].ZBUF.U64) & ZBUF_REG_MASK)
|
||||
m_dirty_gs_regs |= (1 << DIRTY_REG_ZBUF);
|
||||
else
|
||||
m_dirty_gs_regs &= ~(1 << DIRTY_REG_ZBUF);
|
||||
@@ -1919,7 +1919,7 @@ inline bool GSState::TestDrawChanged()
|
||||
// Check if PRIM has changed we need to check if it's just a different triangle or the context is changing.
|
||||
if (m_dirty_gs_regs & (1 << DIRTY_REG_PRIM))
|
||||
{
|
||||
u32 prim_mask = 0x7ff;
|
||||
u32 prim_mask = PRIM_REG_MASK;
|
||||
|
||||
if (GSUtil::GetPrimClass(m_prev_env.PRIM.PRIM) == GSUtil::GetPrimClass(m_env.PRIM.PRIM))
|
||||
prim_mask &= ~0x7;
|
||||
@@ -3994,7 +3994,188 @@ void GSState::CalculatePrimitiveCoversWithoutGaps()
|
||||
m_primitive_covers_without_gaps = SpriteDrawWithoutGaps() ? (m_primitive_covers_without_gaps == GapsFound ? SpriteNoGaps : m_primitive_covers_without_gaps) : GapsFound;
|
||||
}
|
||||
|
||||
__forceinline bool GSState::IsAutoFlushDraw(u32 prim)
|
||||
__forceinline bool GSState::EarlyDetectShuffle(u32 prim)
|
||||
{
|
||||
// We only handle sprites here and need one sprite in the queue.
|
||||
// Texture mapping must be enabled for a shuffle.
|
||||
if (m_index.tail < 2 || prim != GS_SPRITE || !PRIM->TME)
|
||||
return false;
|
||||
|
||||
const GSVertex* RESTRICT vertex = &m_vertex.buff[0];
|
||||
const u16* RESTRICT index = &m_index.buff[0];
|
||||
const GSVector4i& o = m_xyof;
|
||||
|
||||
if (GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp == 16 && GSLocalMemory::m_psm[m_context->TEX0.PSM].bpp == 16)
|
||||
{
|
||||
// Handle shuffles where the source and destination are both 16 bits.
|
||||
|
||||
const int x0 = static_cast<int>(vertex[index[0]].XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX);
|
||||
const int x1 = static_cast<int>(vertex[index[0]].XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX);
|
||||
const int xn = static_cast<int>(m_v.XYZ.X) - static_cast<int>(static_cast<int>(m_context->XYOFFSET.OFX));
|
||||
|
||||
int u0, un;
|
||||
if (PRIM->FST)
|
||||
{
|
||||
u0 = static_cast<int>(vertex[index[0]].U);
|
||||
un = static_cast<int>(m_v.U);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float q0 = vertex[index[0]].RGBAQ.Q == 0.0f ? FLT_MIN : vertex[index[0]].RGBAQ.Q;
|
||||
u0 = static_cast<int>((1 << m_context->TEX0.TW) * (vertex[index[0]].ST.S / q0) * 16.0f);
|
||||
const float qn = m_v.RGBAQ.Q == 0.0f ? FLT_MIN : m_v.RGBAQ.Q;
|
||||
un = static_cast<int>((1 << m_context->TEX0.TW) * (m_v.ST.S / qn) * 16.0f);
|
||||
}
|
||||
|
||||
// Check that the X-U offsets are the same for the first and current vertex and
|
||||
// that the width of the first sprite is at most 16 pixels.
|
||||
return std::abs(u0 - x0) == std::abs(un - xn) && std::abs(x1 - x0) <= 0x100;
|
||||
}
|
||||
|
||||
if (GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp == 16 && GSLocalMemory::m_psm[m_context->TEX0.PSM].bpp == 32)
|
||||
{
|
||||
// Handle shuffles where the source is 32/24 bits and destination is 16 bits.
|
||||
// Example: The Godfather.
|
||||
|
||||
// These shuffles usually mask R and G (lower 10 bits in 16 bit format) so that they
|
||||
// write only to B and A (top 6 bits in 16 bit format).
|
||||
if (GSUtil::GetChannelMask(m_context->FRAME.PSM, m_context->FRAME.FBMSK) != 0xC)
|
||||
return false;
|
||||
|
||||
const int x0 = static_cast<int>(vertex[index[0]].XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX);
|
||||
const int y0 = static_cast<int>(vertex[index[0]].XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY);
|
||||
const int x1 = static_cast<int>(vertex[index[1]].XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX);
|
||||
const int y1 = static_cast<int>(vertex[index[1]].XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY);
|
||||
|
||||
int u0, v0, u1, v1;
|
||||
|
||||
if (PRIM->FST)
|
||||
{
|
||||
u0 = static_cast<int>(vertex[index[0]].U);
|
||||
v0 = static_cast<int>(vertex[index[0]].V);
|
||||
u1 = static_cast<int>(vertex[index[1]].U);
|
||||
v1 = static_cast<int>(vertex[index[1]].V);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float q0 = vertex[index[0]].RGBAQ.Q == 0.0f ? FLT_MIN : vertex[index[0]].RGBAQ.Q;
|
||||
u0 = static_cast<int>((1 << m_context->TEX0.TW) * (vertex[index[0]].ST.S / q0) * 16.0f);
|
||||
v0 = static_cast<int>((1 << m_context->TEX0.TH) * (vertex[index[0]].ST.T / q0) * 16.0f);
|
||||
const float q1 = vertex[index[1]].RGBAQ.Q == 0.0f ? FLT_MIN : vertex[index[1]].RGBAQ.Q;
|
||||
u1 = static_cast<int>((1 << m_context->TEX0.TW) * (vertex[index[1]].ST.S / q0) * 16.0f);
|
||||
v1 = static_cast<int>((1 << m_context->TEX0.TH) * (vertex[index[1]].ST.T / q0) * 16.0f);
|
||||
}
|
||||
|
||||
// Check that the source and destination sprite are exactly 8 pixel squares.
|
||||
// We do not use the current vertex in this check because it doesn't have a
|
||||
// clean correspondence with the first shuffle for 32->16 bit shuffles
|
||||
// (the coordinates manually swizzle between 32 and 16 bits).
|
||||
const bool const_spacing =
|
||||
(std::abs(x1 - x0) == 0x80) && (std::abs(y1 - y0) == 0x80) &&
|
||||
(std::abs(u1 - u0) == 0x80) && (std::abs(v1 - v0) == 0x80);
|
||||
|
||||
// The purpose of these shuffles is to write the alpha channel,
|
||||
// so the coordinates should write to upper 16 bits regions only.
|
||||
const bool write_ba = (std::min(x0, x1) & 0x80) != 0;
|
||||
|
||||
return const_spacing && write_ba;
|
||||
}
|
||||
|
||||
if (GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp == 32 && GSLocalMemory::m_psm[m_context->TEX0.PSM].bpp == 16)
|
||||
{
|
||||
// Handle shuffles where the source is 16 bits and destination is 32/16 bits.
|
||||
// Example: DT Racer.
|
||||
|
||||
// These shuffles usually mask RGB (lower 24 bits in 32 bit format) so that they
|
||||
// write only to A.
|
||||
if (GSUtil::GetChannelMask(m_context->FRAME.PSM, m_context->FRAME.FBMSK) != 8)
|
||||
return false;
|
||||
|
||||
const int x0 = static_cast<int>(vertex[index[0]].XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX);
|
||||
const int y0 = static_cast<int>(vertex[index[0]].XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY);
|
||||
const int x1 = static_cast<int>(vertex[index[1]].XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX);
|
||||
const int y1 = static_cast<int>(vertex[index[1]].XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY);
|
||||
|
||||
int u0, v0, u1, v1;
|
||||
|
||||
if (PRIM->FST)
|
||||
{
|
||||
u0 = static_cast<int>(vertex[index[0]].U);
|
||||
v0 = static_cast<int>(vertex[index[0]].V);
|
||||
u1 = static_cast<int>(vertex[index[1]].U);
|
||||
v1 = static_cast<int>(vertex[index[1]].V);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float q0 = vertex[index[0]].RGBAQ.Q == 0.0f ? FLT_MIN : vertex[index[0]].RGBAQ.Q;
|
||||
u0 = static_cast<int>((1 << m_context->TEX0.TW) * (vertex[index[0]].ST.S / q0) * 16.0f);
|
||||
v0 = static_cast<int>((1 << m_context->TEX0.TH) * (vertex[index[0]].ST.T / q0) * 16.0f);
|
||||
const float q1 = vertex[index[1]].RGBAQ.Q == 0.0f ? FLT_MIN : vertex[index[1]].RGBAQ.Q;
|
||||
u1 = static_cast<int>((1 << m_context->TEX0.TW) * (vertex[index[1]].ST.S / q0) * 16.0f);
|
||||
v1 = static_cast<int>((1 << m_context->TEX0.TH) * (vertex[index[1]].ST.T / q0) * 16.0f);
|
||||
}
|
||||
|
||||
// Check that the source and destination sprite are exactly 8 pixel squares.
|
||||
// We do not use the current vertex in this check because it doesn't have a
|
||||
// clean correspondence with the first shuffle for 32->16 bit shuffles
|
||||
// (the coordinates manually swizzle between 32 and 16 bits).
|
||||
const bool const_spacing =
|
||||
(std::abs(x1 - x0) == 0x80) && (std::abs(y1 - y0) == 0x80) &&
|
||||
(std::abs(u1 - u0) == 0x80) && (std::abs(v1 - v0) == 0x80);
|
||||
|
||||
// The purpose of these shuffles is to read the green channel,
|
||||
// so the coordinates should read the lower 16 bits only.
|
||||
const bool read_rg = (std::min(u0, u1) & 0x80) == 0;
|
||||
|
||||
return const_spacing && read_rg;
|
||||
}
|
||||
|
||||
if (m_context->TEX0.PSM == PSMT8)
|
||||
{
|
||||
// Handle channel shuffles.
|
||||
|
||||
// Heuristics to detect channel shuffle based on first sprite and clamp mode.
|
||||
const auto CheckWidthOrClampMode = [this]() -> bool {
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
|
||||
const int draw_width = std::abs(v[1].XYZ.X - v[0].XYZ.X) >> 4;
|
||||
const int draw_height = std::abs(v[1].XYZ.Y - v[0].XYZ.Y) >> 4;
|
||||
|
||||
// Checks if using region clamp or region repeat for U or V.
|
||||
// Might used used when the sprites are 16 pixels wide.
|
||||
const bool clamp_region = ((m_context->CLAMP.WMS | m_context->CLAMP.WMT) & 0x2) != 0;
|
||||
|
||||
// Channel shuffles usually draw 8 x 2 sprites.
|
||||
const bool draw_match = (draw_height == 2) || (draw_width == 8);
|
||||
|
||||
return draw_match || clamp_region;
|
||||
};
|
||||
|
||||
const bool single_page_x = temp_draw_rect.width() <= 64;
|
||||
const bool single_page_y = temp_draw_rect.height() <= 64;
|
||||
if (single_page_x && single_page_y)
|
||||
{
|
||||
return CheckWidthOrClampMode();
|
||||
}
|
||||
else if (!single_page_x)
|
||||
{
|
||||
// Not a single page in width.
|
||||
return false;
|
||||
}
|
||||
|
||||
// WRC 4 does channel shuffles in vertical strips. So check for page alignment.
|
||||
// Texture TBW should also be twice the framebuffer FBW, because the page is twice as wide.
|
||||
if (m_context->TEX0.TBW == (m_context->FRAME.FBW * 2) &&
|
||||
GSLocalMemory::IsPageAligned(m_context->FRAME.PSM, temp_draw_rect))
|
||||
{
|
||||
return CheckWidthOrClampMode();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
__forceinline bool GSState::IsAutoFlushDraw(u32 prim, int& tex_layer)
|
||||
{
|
||||
if (!PRIM->TME || (GSConfig.UserHacks_AutoFlush == GSHWAutoFlushLevel::SpritesOnly && prim != GS_SPRITE))
|
||||
return false;
|
||||
@@ -4004,24 +4185,56 @@ __forceinline bool GSState::IsAutoFlushDraw(u32 prim)
|
||||
return false;
|
||||
|
||||
// Try to detect shuffles, because these will not autoflush, they by design clash.
|
||||
if (GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp == 16 && GSLocalMemory::m_psm[m_context->TEX0.PSM].bpp == 16)
|
||||
{
|
||||
// Pretty confident here...
|
||||
GSVertex* buffer = &m_vertex.buff[0];
|
||||
const bool const_spacing = std::abs(buffer[m_index.buff[0]].U - buffer[m_index.buff[0]].XYZ.X) == std::abs(m_v.U - m_v.XYZ.X) && std::abs(buffer[m_index.buff[1]].XYZ.X - buffer[m_index.buff[0]].XYZ.X) <= 256; // Lequal to 16 pixels apart.
|
||||
if (EarlyDetectShuffle(prim))
|
||||
return false;
|
||||
|
||||
if (const_spacing)
|
||||
return false;
|
||||
// Check if one of the texture being used is the same as the FRAME or ZBUF.
|
||||
// In the case of possible mip-mapping, we need to check all possible layers.
|
||||
bool frame_addr_hit = false;
|
||||
bool zbuf_addr_hit = false;
|
||||
const bool possible_mip_map = m_context->TEX1.MXL > 0 && m_context->TEX1.MMIN >= 2 && m_context->TEX1.MMIN <= 5;
|
||||
int min_possible_layer = 0;
|
||||
int max_possible_layer = 0;
|
||||
if (possible_mip_map)
|
||||
{
|
||||
if (m_context->TEX1.LCM)
|
||||
{
|
||||
// Fixed LOD.
|
||||
min_possible_layer = std::clamp(m_context->TEX1.K >> 4, 0, static_cast<int>(m_context->TEX1.MXL));
|
||||
max_possible_layer = std::clamp((m_context->TEX1.K + 0xF) >> 4, 0, static_cast<int>(m_context->TEX1.MXL));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Variable LOD based on vertex Q.
|
||||
max_possible_layer = static_cast<int>(m_context->TEX1.MXL);
|
||||
}
|
||||
}
|
||||
|
||||
GIFRegTEX0 TEX0_hit;
|
||||
for (tex_layer = min_possible_layer; tex_layer <= max_possible_layer; tex_layer++)
|
||||
{
|
||||
TEX0_hit = GetTex0Layer(tex_layer);
|
||||
if (TEX0_hit.TBP0 == m_context->FRAME.Block())
|
||||
{
|
||||
frame_addr_hit = true;
|
||||
break;
|
||||
}
|
||||
if (TEX0_hit.TBP0 == m_context->ZBUF.Block())
|
||||
{
|
||||
zbuf_addr_hit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const u32 frame_mask = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
const bool frame_hit = m_context->FRAME.Block() == m_context->TEX0.TBP0 && !(m_context->TEST.ATE && m_context->TEST.ATST == 0 && m_context->TEST.AFAIL == 2) && ((m_context->FRAME.FBMSK & frame_mask) != frame_mask);
|
||||
const bool frame_hit = frame_addr_hit && !(m_context->TEST.ATE && m_context->TEST.ATST == 0 && m_context->TEST.AFAIL == 2) && ((m_context->FRAME.FBMSK & frame_mask) != frame_mask);
|
||||
// There's a strange behaviour we need to test on a PS2 here, if the FRAME is a Z format, like Powerdrome something swaps over, and it seems Alpha Fail of "FB Only" writes to the Z.. it's odd.
|
||||
const bool z_needed = !(m_context->TEST.ATE && m_context->TEST.ATST == 0 && m_context->TEST.AFAIL != 2) && !m_context->ZBUF.ZMSK;
|
||||
const bool zbuf_hit = (m_context->ZBUF.Block() == m_context->TEX0.TBP0) && z_needed;
|
||||
const bool zbuf_hit = zbuf_addr_hit && z_needed;
|
||||
const u32 frame_z_psm = frame_hit ? m_context->FRAME.PSM : m_context->ZBUF.PSM;
|
||||
const u32 frame_z_bp = frame_hit ? m_context->FRAME.Block() : m_context->ZBUF.Block();
|
||||
|
||||
if ((frame_hit || zbuf_hit) && GSUtil::HasSharedBits(frame_z_bp, frame_z_psm, m_context->TEX0.TBP0, m_context->TEX0.PSM))
|
||||
if ((frame_hit || zbuf_hit) && GSUtil::HasSharedBits(frame_z_bp, frame_z_psm, TEX0_hit.TBP0, TEX0_hit.PSM))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -4109,7 +4322,8 @@ __forceinline void GSState::HandleAutoFlush()
|
||||
// To briefly explain what's going on here, what we are checking for is draws over a texture when the source and destination are themselves.
|
||||
// Because one page of the texture gets buffered in the Texture Cache (the PS2's one) if any of those pixels are overwritten, you still read the old data.
|
||||
// So we need to calculate if a page boundary is being crossed for the format it is in and if the same part of the texture being written and read inside the draw.
|
||||
if (IsAutoFlushDraw(prim))
|
||||
int tex_layer = 0;
|
||||
if (IsAutoFlushDraw(prim, tex_layer))
|
||||
{
|
||||
int n = 1;
|
||||
u32 buff[3];
|
||||
@@ -4144,23 +4358,37 @@ __forceinline void GSState::HandleAutoFlush()
|
||||
break;
|
||||
}
|
||||
|
||||
const bool possible_mipmap = m_context->TEX1.MXL > 0 && m_context->TEX1.MMIN >= 2 && m_context->TEX1.MMIN <= 5;
|
||||
const float K = static_cast<float>(m_context->TEX1.K) / 16;
|
||||
const float powL = static_cast<float>(1 << m_context->TEX1.L);
|
||||
|
||||
GSVector4i xy_coord;
|
||||
GSVector4i tex_coord;
|
||||
float vert_lod = K;
|
||||
|
||||
// Prepare the currently processed vertex.
|
||||
xy_coord.x = (static_cast<int>(m_v.XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX)) >> 4;
|
||||
xy_coord.y = (static_cast<int>(m_v.XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY)) >> 4;
|
||||
if (PRIM->FST)
|
||||
{
|
||||
tex_coord.x = m_v.U >> 4;
|
||||
tex_coord.y = m_v.V >> 4;
|
||||
tex_coord.x = (m_v.U >> 4) >> tex_layer;
|
||||
tex_coord.y = (m_v.V >> 4) >> tex_layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float s = std::min((m_v.ST.S / m_v.RGBAQ.Q), 1.0f);
|
||||
const float t = std::min((m_v.ST.T / m_v.RGBAQ.Q), 1.0f);
|
||||
|
||||
tex_coord.x = static_cast<int>((1 << m_context->TEX0.TW) * s);
|
||||
tex_coord.y = static_cast<int>((1 << m_context->TEX0.TH) * t);
|
||||
tex_coord.x = static_cast<int>((1 << m_context->TEX0.TW) * s) >> tex_layer;
|
||||
tex_coord.y = static_cast<int>((1 << m_context->TEX0.TH) * t) >> tex_layer;
|
||||
|
||||
if (possible_mipmap && !m_context->TEX1.LCM)
|
||||
vert_lod = -std::log2(std::abs(m_v.RGBAQ.Q)) * powL + K;
|
||||
}
|
||||
|
||||
GSVector4i xy_rect = xy_coord.xyxy();
|
||||
GSVector4i tex_rect = tex_coord.xyxy();
|
||||
GSVector2i lod_range = GSVector2i(static_cast<int>(std::floor(vert_lod)), static_cast<int>(std::ceil(vert_lod)));
|
||||
|
||||
const GSLocalMemory::psm_t tex_psm = GSLocalMemory::m_psm[m_context->TEX0.PSM];
|
||||
const GSLocalMemory::psm_t frame_psm = GSLocalMemory::m_psm[m_context->FRAME.PSM];
|
||||
@@ -4169,53 +4397,76 @@ __forceinline void GSState::HandleAutoFlush()
|
||||
{
|
||||
const GSVertex* v = &m_vertex.buff[buff[i]];
|
||||
|
||||
xy_coord.x = (static_cast<int>(v->XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX)) >> 4;
|
||||
xy_coord.y = (static_cast<int>(v->XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY)) >> 4;
|
||||
if (PRIM->FST)
|
||||
{
|
||||
tex_coord.x = v->U >> 4;
|
||||
tex_coord.y = v->V >> 4;
|
||||
tex_coord.x = (v->U >> 4) >> tex_layer;
|
||||
tex_coord.y = (v->V >> 4) >> tex_layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float s = std::min((v->ST.S / v->RGBAQ.Q), 1.0f);
|
||||
const float t = std::min((v->ST.T / v->RGBAQ.Q), 1.0f);
|
||||
|
||||
tex_coord.x = static_cast<int>(std::round((1 << m_context->TEX0.TW) * s));
|
||||
tex_coord.y = static_cast<int>(std::round((1 << m_context->TEX0.TH) * t));
|
||||
tex_coord.x = static_cast<int>(std::round((1 << m_context->TEX0.TW) * s)) >> tex_layer;
|
||||
tex_coord.y = static_cast<int>(std::round((1 << m_context->TEX0.TH) * t)) >> tex_layer;
|
||||
|
||||
if (possible_mipmap && !m_context->TEX1.LCM)
|
||||
vert_lod = -std::log2(std::abs(v->RGBAQ.Q)) * powL + K;
|
||||
}
|
||||
|
||||
xy_rect.x = std::min(xy_rect.x, xy_coord.x);
|
||||
xy_rect.z = std::max(xy_rect.z, xy_coord.x);
|
||||
xy_rect.y = std::min(xy_rect.y, xy_coord.y);
|
||||
xy_rect.w = std::max(xy_rect.w, xy_coord.y);
|
||||
tex_rect.x = std::min(tex_rect.x, tex_coord.x);
|
||||
tex_rect.z = std::max(tex_rect.z, tex_coord.x);
|
||||
tex_rect.y = std::min(tex_rect.y, tex_coord.y);
|
||||
tex_rect.w = std::max(tex_rect.w, tex_coord.y);
|
||||
lod_range.x = std::min(lod_range.x, static_cast<int>(std::floor(vert_lod)));
|
||||
lod_range.y = std::max(lod_range.y, static_cast<int>(std::ceil(vert_lod)));
|
||||
}
|
||||
|
||||
// If the current prim does not use the correct mipmap layer then we don't need to flush.
|
||||
if (possible_mipmap && !(lod_range.x <= tex_layer && tex_layer <= lod_range.y))
|
||||
return;
|
||||
|
||||
// If the draw was 1 line thick, make it larger as rects are exclusive of ends.
|
||||
if (xy_rect.x == xy_rect.z)
|
||||
xy_rect += GSVector4i::cxpr(0, 0, 1, 0);
|
||||
if (xy_rect.y == xy_rect.w)
|
||||
xy_rect += GSVector4i::cxpr(0, 0, 0, 1);
|
||||
if (tex_rect.x == tex_rect.z)
|
||||
tex_rect += GSVector4i::cxpr(0, 0, 1, 0);
|
||||
if (tex_rect.y == tex_rect.w)
|
||||
tex_rect += GSVector4i::cxpr(0, 0, 0, 1);
|
||||
|
||||
// If the current prim fails the scissor test then we don't need to flush.
|
||||
if (xy_rect.rintersect(m_context->scissor.in).rempty())
|
||||
return;
|
||||
|
||||
// Get the last texture position from the last draw.
|
||||
const GSVertex* v = &m_vertex.buff[m_index.buff[m_index.tail - 1]];
|
||||
|
||||
if (PRIM->FST)
|
||||
{
|
||||
tex_coord.x = v->U >> 4;
|
||||
tex_coord.y = v->V >> 4;
|
||||
tex_coord.x = (v->U >> 4) >> tex_layer;
|
||||
tex_coord.y = (v->V >> 4) >> tex_layer;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float s = std::min((v->ST.S / v->RGBAQ.Q), 1.0f);
|
||||
const float t = std::min((v->ST.T / v->RGBAQ.Q), 1.0f);
|
||||
|
||||
tex_coord.x = static_cast<int>(std::round((1 << m_context->TEX0.TW) * s));
|
||||
tex_coord.y = static_cast<int>(std::round((1 << m_context->TEX0.TH) * t));
|
||||
tex_coord.x = static_cast<int>(std::round((1 << m_context->TEX0.TW) * s)) >> tex_layer;
|
||||
tex_coord.y = static_cast<int>(std::round((1 << m_context->TEX0.TH) * t)) >> tex_layer;
|
||||
}
|
||||
|
||||
const int clamp_minu = m_context->CLAMP.MINU;
|
||||
const int clamp_maxu = m_context->CLAMP.MAXU;
|
||||
const int clamp_minv = m_context->CLAMP.MINV;
|
||||
const int clamp_maxv = m_context->CLAMP.MAXV;
|
||||
const int clamp_minu = m_context->CLAMP.MINU >> tex_layer;
|
||||
const int clamp_maxu = m_context->CLAMP.MAXU >> tex_layer;
|
||||
const int clamp_minv = m_context->CLAMP.MINV >> tex_layer;
|
||||
const int clamp_maxv = m_context->CLAMP.MAXV >> tex_layer;
|
||||
|
||||
switch (m_context->CLAMP.WMS)
|
||||
{
|
||||
@@ -4351,7 +4602,7 @@ __forceinline void GSState::HandleAutoFlush()
|
||||
const int tex_width = (m_context->TEX0.TBW * 64) / tex_psm.pgs.x;
|
||||
if ((frame_width == tex_width) || ((tex_rect.w / tex_psm.pgs.y) <= 1 && frame_width >= tex_width))
|
||||
{
|
||||
tex_rect += GSVector4i(0, 0, tex_page_mask.z, tex_page_mask.w); // round up to the next page as we will be comparing by page.
|
||||
tex_rect += GSVector4i(0, 0, tex_psm.pgs.x - 1, tex_psm.pgs.y - 1); // round up to the next page as we will be comparing by page.
|
||||
//We know we've changed page, so let's set the dimension to cover the page they're in (for different pixel orders)
|
||||
tex_rect &= tex_page_mask;
|
||||
tex_rect = GSVector4i(tex_rect.x / tex_psm.pgs.x, tex_rect.y / tex_psm.pgs.y, tex_rect.z / tex_psm.pgs.x, tex_rect.w / tex_psm.pgs.y);
|
||||
@@ -4360,7 +4611,7 @@ __forceinline void GSState::HandleAutoFlush()
|
||||
const int frame_page_mask_y = ~(frame_psm.pgs.y - 1);
|
||||
const GSVector4i frame_page_mask = { frame_page_mask_x, frame_page_mask_y, frame_page_mask_x, frame_page_mask_y };
|
||||
GSVector4i area_out = temp_draw_rect;
|
||||
area_out += GSVector4i(0, 0, frame_page_mask.z, frame_page_mask.w); // round up to the next page as we will be comparing by page.
|
||||
area_out += GSVector4i(0, 0, frame_psm.pgs.x - 1, frame_psm.pgs.y - 1); // round up to the next page as we will be comparing by page.
|
||||
area_out &= frame_page_mask;
|
||||
area_out = GSVector4i(area_out.x / frame_psm.pgs.x, area_out.y / frame_psm.pgs.y, area_out.z / frame_psm.pgs.x, area_out.w / frame_psm.pgs.y);
|
||||
|
||||
|
||||
@@ -171,8 +171,9 @@ protected:
|
||||
void UpdateVertexKick();
|
||||
|
||||
void GrowVertexBuffer();
|
||||
bool IsAutoFlushDraw(u32 prim);
|
||||
bool IsAutoFlushDraw(u32 prim, int& tex_layer);
|
||||
template<u32 prim> void HandleAutoFlush();
|
||||
bool EarlyDetectShuffle(u32 prim);
|
||||
void CheckCLUTValidity(u32 prim);
|
||||
|
||||
template <u32 prim, bool auto_flush> void VertexKick(u32 skip);
|
||||
@@ -270,6 +271,20 @@ public:
|
||||
|
||||
static constexpr u32 STATE_VERSION = 9;
|
||||
|
||||
#define PRIM_REG_MASK 0x7FF
|
||||
#define MIPTBP_REG_MASK ((1ULL << 60) - 1ULL)
|
||||
#define CLAMP_REG_MASK ((1ULL << 44) - 1ULL)
|
||||
#define TEX1_REG_MASK 0xFFF001803FDULL
|
||||
#define XYOFFSET_REG_MASK 0x0000FFFF0000FFFFULL
|
||||
#define TEXA_REG_MASK 0xFF000080FFULL
|
||||
#define FOGCOL_REG_MASK 0xFFFFFF
|
||||
#define SCISSOR_REG_MASK 0x7FF07FF07FF07FFULL
|
||||
#define ALPHA_REG_MASK 0xFF000000FFULL
|
||||
#define DIMX_REG_MASK 0x7777777777777777ULL
|
||||
#define FRAME_REG_MASK 0xFFFFFFFF3F3F01FFULL
|
||||
#define ZBUF_REG_MASK 0x10F0001FFULL
|
||||
#define TEST_REG_MASK 0x7FFFF
|
||||
|
||||
enum REG_DIRTY
|
||||
{
|
||||
DIRTY_REG_ALPHA,
|
||||
|
||||
@@ -723,6 +723,39 @@ GSTexture* GSDevice::CreateTexture(int w, int h, int mipmap_levels, GSTexture::F
|
||||
return FetchSurface(GSTexture::Type::Texture, w, h, levels, format, false, m_features.prefer_new_textures && !prefer_reuse);
|
||||
}
|
||||
|
||||
void GSDevice::DoStretchRectWithAssertions(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
|
||||
{
|
||||
pxAssert((dTex && dTex->IsDepthStencil()) == HasDepthOutput(shader));
|
||||
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
|
||||
GL_INS("StretchRect(%d) {%d,%d} %dx%d -> {%d,%d) %dx%d", shader, int(sRect.left), int(sRect.top),
|
||||
int(sRect.right - sRect.left), int(sRect.bottom - sRect.top), int(dRect.left), int(dRect.top),
|
||||
int(dRect.right - dRect.left), int(dRect.bottom - dRect.top));
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, cms, shader, linear);
|
||||
}
|
||||
|
||||
void GSDevice::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{
|
||||
GSHWDrawConfig::ColorMaskSelector cms;
|
||||
|
||||
cms.wr = red;
|
||||
cms.wg = green;
|
||||
cms.wb = blue;
|
||||
cms.wa = alpha;
|
||||
|
||||
pxAssert(HasVariableWriteMask(shader));
|
||||
GL_INS("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", cms.wr, cms.wg, cms.wb, cms.wa);
|
||||
|
||||
DoStretchRectWithAssertions(sTex, sRect, dTex, dRect, cms, shader, false);
|
||||
}
|
||||
|
||||
void GSDevice::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
ShaderConvert shader, bool linear)
|
||||
{
|
||||
DoStretchRectWithAssertions(sTex, sRect, dTex, dRect, GSHWDrawConfig::ColorMaskSelector(ShaderConvertWriteMask(shader)), shader, linear);
|
||||
}
|
||||
|
||||
void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
{
|
||||
StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear);
|
||||
@@ -734,11 +767,11 @@ void GSDevice::DrawMultiStretchRects(
|
||||
for (u32 i = 0; i < num_rects; i++)
|
||||
{
|
||||
const MultiStretchRect& sr = rects[i];
|
||||
pxAssert(shader == ShaderConvert::COPY || shader == ShaderConvert::RTA_CORRECTION || rects[0].wmask.wrgba == 0xf);
|
||||
pxAssert(HasVariableWriteMask(shader) || rects[0].wmask.wrgba == 0xf);
|
||||
if (rects[0].wmask.wrgba != 0xf)
|
||||
{
|
||||
g_gs_device->StretchRect(sr.src, sr.src_rect, dTex, sr.dst_rect, rects[0].wmask.wr,
|
||||
rects[0].wmask.wg, rects[0].wmask.wb, rects[0].wmask.wa);
|
||||
rects[0].wmask.wg, rects[0].wmask.wb, rects[0].wmask.wa, shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "GS/GS.h"
|
||||
#include "GS/Renderers/Common/GSFastList.h"
|
||||
#include "GS/Renderers/Common/GSTexture.h"
|
||||
#include "GS/Renderers/Vulkan/GSTextureVK.h"
|
||||
#include "GS/Renderers/Common/GSVertex.h"
|
||||
#include "GS/GSAlignedClass.h"
|
||||
#include "GS/GSExtra.h"
|
||||
@@ -69,6 +68,27 @@ enum class ShaderInterlace
|
||||
Count
|
||||
};
|
||||
|
||||
static inline bool HasVariableWriteMask(ShaderConvert shader)
|
||||
{
|
||||
switch (shader)
|
||||
{
|
||||
case ShaderConvert::COPY:
|
||||
case ShaderConvert::RTA_CORRECTION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int GetShaderIndexForMask(ShaderConvert shader, int mask)
|
||||
{
|
||||
pxAssert(HasVariableWriteMask(shader));
|
||||
int index = mask;
|
||||
if (shader == ShaderConvert::RTA_CORRECTION)
|
||||
index |= 1 << 4;
|
||||
return index;
|
||||
}
|
||||
|
||||
static inline bool HasDepthOutput(ShaderConvert shader)
|
||||
{
|
||||
switch (shader)
|
||||
@@ -549,6 +569,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
constexpr ColorMaskSelector(): key(0xF) {}
|
||||
constexpr ColorMaskSelector(u8 c): key(0) { wrgba = c; }
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
struct alignas(16) VSConstantBuffer
|
||||
{
|
||||
@@ -922,6 +943,12 @@ protected:
|
||||
/// Perform texture operations for ImGui
|
||||
void UpdateImGuiTextures();
|
||||
|
||||
protected:
|
||||
// Entry point to the renderer-specific StretchRect code.
|
||||
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) = 0;
|
||||
void DoStretchRectWithAssertions(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear);
|
||||
|
||||
public:
|
||||
GSDevice();
|
||||
virtual ~GSDevice();
|
||||
@@ -1037,9 +1064,9 @@ public:
|
||||
virtual std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) = 0;
|
||||
|
||||
virtual void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) = 0;
|
||||
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) = 0;
|
||||
virtual void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) = 0;
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true);
|
||||
|
||||
/// Performs a screen blit for display. If dTex is null, it assumes you are writing to the system framebuffer/swap chain.
|
||||
|
||||
@@ -1274,28 +1274,18 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
||||
dTex->SetState(GSTexture::State::Dirty);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
|
||||
{
|
||||
pxAssert(dTex->IsDepthStencil() == HasDepthOutput(shader));
|
||||
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr,
|
||||
m_convert.bs[ShaderConvertWriteMask(shader)].get(), linear);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr, m_convert.bs[cms.wrgba].get(), linear);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear)
|
||||
void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear)
|
||||
{
|
||||
StretchRect(sTex, sRect, dTex, dRect, ps, ps_cb, m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), linear);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, ps, ps_cb, m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), linear);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{
|
||||
const u8 index = static_cast<u8>(red) | (static_cast<u8>(green) << 1) | (static_cast<u8>(blue) << 2) |
|
||||
(static_cast<u8>(alpha) << 3);
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr,
|
||||
m_convert.bs[index].get(), false);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear)
|
||||
void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear)
|
||||
{
|
||||
CommitClear(sTex);
|
||||
|
||||
@@ -1439,7 +1429,7 @@ void GSDevice11::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u
|
||||
|
||||
const GSVector4 dRect(0, 0, dSize, 1);
|
||||
const ShaderConvert shader = (dSize == 16) ? ShaderConvert::CLUT_4 : ShaderConvert::CLUT_8;
|
||||
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
}
|
||||
|
||||
void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
|
||||
@@ -1457,7 +1447,7 @@ void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offs
|
||||
|
||||
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
|
||||
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
}
|
||||
|
||||
void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect)
|
||||
@@ -1477,7 +1467,7 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
|
||||
const ShaderConvert shader = ShaderConvert::DOWNSAMPLE_COPY;
|
||||
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
}
|
||||
|
||||
void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader)
|
||||
@@ -1596,7 +1586,7 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
|
||||
// Save 2nd output
|
||||
if (feedback_write_2)
|
||||
{
|
||||
StretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
|
||||
DoStretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
|
||||
m_merge.cb.get(), nullptr, linear);
|
||||
}
|
||||
|
||||
@@ -1607,12 +1597,12 @@ void GSDevice11::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
|
||||
if (sTex[0])
|
||||
{
|
||||
// 1st output is enabled. It must be blended
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[PMODE.MMOD].get(), m_merge.cb.get(), m_merge.bs.get(), linear);
|
||||
DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge.ps[PMODE.MMOD].get(), m_merge.cb.get(), m_merge.bs.get(), linear);
|
||||
}
|
||||
|
||||
if (feedback_write_1)
|
||||
{
|
||||
StretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
|
||||
DoStretchRect(dTex, full_r, sTex[2], dRect[2], m_convert.ps[static_cast<int>(ShaderConvert::YUV)].get(),
|
||||
m_merge.cb.get(), nullptr, linear);
|
||||
}
|
||||
}
|
||||
@@ -1621,7 +1611,7 @@ void GSDevice11::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
{
|
||||
m_ctx->UpdateSubresource(m_interlace.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), linear);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)].get(), m_interlace.cb.get(), linear);
|
||||
}
|
||||
|
||||
void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex)
|
||||
@@ -1647,7 +1637,7 @@ void GSDevice11::DoFXAA(GSTexture* sTex, GSTexture* dTex)
|
||||
return;
|
||||
}
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_fxaa_ps.get(), nullptr, true);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa_ps.get(), nullptr, true);
|
||||
}
|
||||
|
||||
void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float params[4])
|
||||
@@ -1659,7 +1649,7 @@ void GSDevice11::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float para
|
||||
|
||||
m_ctx->UpdateSubresource(m_shadeboost.cb.get(), 0, nullptr, params, 0, 0);
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps.get(), m_shadeboost.cb.get(), false);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps.get(), m_shadeboost.cb.get(), false);
|
||||
}
|
||||
|
||||
void GSDevice11::SetupVS(VSSelector sel, const GSHWDrawConfig::VSConstantBuffer* cb)
|
||||
@@ -2158,7 +2148,7 @@ void GSDevice11::RenderImGui()
|
||||
m_ctx->IASetVertexBuffers(0, 1, m_vb.addressof(), &m_state.vb_stride, &vb_offset);
|
||||
}
|
||||
|
||||
void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm)
|
||||
void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox)
|
||||
{
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
@@ -2179,6 +2169,17 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
|
||||
|
||||
// ia
|
||||
|
||||
const GSVector4 src = GSVector4(bbox) / GSVector4(ds->GetSize()).xyxy();
|
||||
const GSVector4 dst = src * 2.0f - 1.0f;
|
||||
|
||||
const GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
|
||||
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
|
||||
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), 4);
|
||||
IASetInputLayout(m_convert.il.get());
|
||||
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
@@ -2447,7 +2448,7 @@ void GSDevice11::PSUnbindConflictingSRVs(GSTexture* tex1, GSTexture* tex2)
|
||||
bool changed = false;
|
||||
for (size_t i = 0; i < m_state.ps_sr_views.size(); i++)
|
||||
{
|
||||
if ((tex1 && m_state.ps_sr_views[i] == *(GSTexture11*)tex1) || (tex2 && m_state.ps_sr_views[i] == *(GSTexture11*)tex2))
|
||||
if ((tex1 && m_state.ps_sr_views[i] == *static_cast<GSTexture11*>(tex1)) || (tex2 && m_state.ps_sr_views[i] == *static_cast<GSTexture11*>(tex2)))
|
||||
{
|
||||
m_state.ps_sr_views[i] = nullptr;
|
||||
changed = true;
|
||||
@@ -2624,6 +2625,8 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
// Destination Alpha Setup
|
||||
const bool multidraw_fb_copy = m_features.multidraw_fb_copy && (config.require_one_barrier || config.require_full_barrier);
|
||||
GSTexture* primid_texture = nullptr;
|
||||
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking)
|
||||
{
|
||||
@@ -2634,25 +2637,12 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
return;
|
||||
}
|
||||
|
||||
StretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
DoStretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
primid_texture, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
|
||||
}
|
||||
else if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne)
|
||||
{
|
||||
const GSVector4 src = GSVector4(config.drawarea) / GSVector4(config.ds->GetSize()).xyxy();
|
||||
const GSVector4 dst = src * 2.0f - 1.0f;
|
||||
|
||||
GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(dst.x, -dst.y, 0.5f, 1.0f), GSVector2(src.x, src.y)},
|
||||
{GSVector4(dst.z, -dst.y, 0.5f, 1.0f), GSVector2(src.z, src.y)},
|
||||
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
|
||||
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, vertices, config.datm);
|
||||
}
|
||||
(config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne && !multidraw_fb_copy))
|
||||
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, config.datm, config.drawarea);
|
||||
|
||||
if (config.vs.expand != GSHWDrawConfig::VSExpand::None)
|
||||
{
|
||||
@@ -2697,8 +2687,13 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
IASetPrimitiveTopology(topology);
|
||||
|
||||
// Depth testing and sampling, bind resource as dsv read only and srv at the same time without the need of a copy.
|
||||
ID3D11DepthStencilView* read_only_dsv = nullptr;
|
||||
if (config.tex && config.tex == config.ds)
|
||||
read_only_dsv = static_cast<GSTexture11*>(config.ds)->ReadOnlyDepthStencilView();
|
||||
|
||||
// Should be called before changing local srv state.
|
||||
PSUnbindConflictingSRVs(colclip_rt ? colclip_rt : config.rt, config.ds);
|
||||
PSUnbindConflictingSRVs(colclip_rt ? colclip_rt : config.rt, read_only_dsv ? nullptr : config.ds);
|
||||
|
||||
if (config.tex)
|
||||
{
|
||||
@@ -2714,11 +2709,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
SetupVS(config.vs, &config.cb_vs);
|
||||
SetupPS(config.ps, &config.cb_ps, config.sampler);
|
||||
|
||||
// Depth testing and sampling, bind resource as dsv read only and srv at the same time without the need of a copy.
|
||||
ID3D11DepthStencilView* read_only_dsv = nullptr;
|
||||
if (config.tex && config.tex == config.ds)
|
||||
read_only_dsv = static_cast<GSTexture11*>(config.ds)->ReadOnlyDepthStencilView();
|
||||
|
||||
if (primid_texture)
|
||||
{
|
||||
OMDepthStencilSelector dss = config.depth;
|
||||
@@ -2766,6 +2756,11 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor, read_only_dsv);
|
||||
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
|
||||
|
||||
// Clear stencil as close as possible to the RT bind, to avoid framebuffer swaps.
|
||||
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne && multidraw_fb_copy)
|
||||
m_ctx->ClearDepthStencilView(*static_cast<GSTexture11*>(draw_ds), D3D11_CLEAR_STENCIL, 0.0f, 1);
|
||||
|
||||
SendHWDraw(config, draw_rt_clone, draw_rt, config.require_one_barrier, config.require_full_barrier, false);
|
||||
|
||||
if (config.blend_multi_pass.enable)
|
||||
|
||||
@@ -253,6 +253,10 @@ private:
|
||||
D3D11ShaderCache m_shader_cache;
|
||||
std::string m_tfx_source;
|
||||
|
||||
protected:
|
||||
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
|
||||
|
||||
public:
|
||||
GSDevice11();
|
||||
~GSDevice11() override;
|
||||
@@ -298,10 +302,8 @@ public:
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear = true);
|
||||
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear);
|
||||
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear);
|
||||
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override;
|
||||
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
|
||||
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM) override;
|
||||
@@ -309,7 +311,7 @@ public:
|
||||
void DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader) override;
|
||||
void DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, const GSVector2& ds);
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox);
|
||||
|
||||
void* IAMapVertexBuffer(u32 stride, u32 count);
|
||||
void IAUnmapVertexBuffer(u32 stride, u32 count);
|
||||
|
||||
@@ -1425,30 +1425,17 @@ void GSDevice12::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
||||
dTex12->SetState(GSTexture::State::Dirty);
|
||||
}
|
||||
|
||||
void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
ShaderConvert shader /* = ShaderConvert::COPY */, bool linear /* = true */)
|
||||
void GSDevice12::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
|
||||
{
|
||||
pxAssert(HasDepthOutput(shader) == (dTex && dTex->GetType() == GSTexture::Type::DepthStencil));
|
||||
|
||||
GL_INS("StretchRect(%d) {%d,%d} %dx%d -> {%d,%d) %dx%d", shader, int(sRect.left), int(sRect.top),
|
||||
int(sRect.right - sRect.left), int(sRect.bottom - sRect.top), int(dRect.left), int(dRect.top),
|
||||
int(dRect.right - dRect.left), int(dRect.bottom - dRect.top));
|
||||
|
||||
const bool allow_discard = (cms.wrgba == 0xf);
|
||||
const ID3D12PipelineState* state;
|
||||
if (HasVariableWriteMask(shader))
|
||||
state = m_color_copy[GetShaderIndexForMask(shader, cms.wrgba)].get();
|
||||
else
|
||||
state = dTex ? m_convert[static_cast<int>(shader)].get() : m_present[static_cast<int>(shader)].get();
|
||||
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
|
||||
dTex ? m_convert[static_cast<int>(shader)].get() : m_present[static_cast<int>(shader)].get(), linear,
|
||||
ShaderConvertWriteMask(shader) == 0xf);
|
||||
}
|
||||
|
||||
void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
|
||||
bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{
|
||||
GL_PUSH("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", red, green, blue, alpha);
|
||||
|
||||
const u32 index = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
|
||||
int rta_offset = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
|
||||
const bool allow_discard = (index == 0xf);
|
||||
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
|
||||
m_color_copy[index + rta_offset].get(), false, allow_discard);
|
||||
state, linear, allow_discard);
|
||||
}
|
||||
|
||||
void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
@@ -1639,10 +1626,10 @@ void GSDevice12::DoMultiStretchRects(
|
||||
SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
SetUtilityTexture(rects[0].src, rects[0].linear ? m_linear_sampler_cpu : m_point_sampler_cpu);
|
||||
|
||||
pxAssert(shader == ShaderConvert::COPY || shader == ShaderConvert::RTA_CORRECTION || rects[0].wmask.wrgba == 0xf);
|
||||
int rta_bit = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
|
||||
SetPipeline((rects[0].wmask.wrgba != 0xf) ? m_color_copy[rects[0].wmask.wrgba | rta_bit].get() :
|
||||
m_convert[static_cast<int>(shader)].get());
|
||||
pxAssert(HasVariableWriteMask(shader) || rects[0].wmask.wrgba == 0xf);
|
||||
SetPipeline((rects[0].wmask.wrgba != 0xf) ?
|
||||
m_color_copy[GetShaderIndexForMask(shader, rects[0].wmask.wrgba)].get() :
|
||||
m_convert[static_cast<int>(shader)].get());
|
||||
|
||||
if (ApplyUtilityState())
|
||||
DrawIndexedPrimitive();
|
||||
@@ -3831,8 +3818,12 @@ GSTexture12* GSDevice12::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
||||
void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
// Destination Alpha Setup
|
||||
const bool stencil_DATE = (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne);
|
||||
const bool stencil_DATE_One = config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne;
|
||||
const bool stencil_DATE = (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil || stencil_DATE_One);
|
||||
|
||||
// TODO: Backport from vk.
|
||||
if (stencil_DATE_One)
|
||||
config.ps.date = 0;
|
||||
|
||||
GSTexture12* colclip_rt = static_cast<GSTexture12*>(g_gs_device->GetColorClipTexture());
|
||||
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
|
||||
@@ -390,6 +390,10 @@ private:
|
||||
|
||||
void DestroyResources();
|
||||
|
||||
protected:
|
||||
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
|
||||
|
||||
public:
|
||||
GSDevice12();
|
||||
~GSDevice12() override;
|
||||
@@ -428,10 +432,6 @@ public:
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
|
||||
bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
|
||||
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
PresentShader shader, float shaderTime, bool linear) override;
|
||||
void UpdateCLUTTexture(
|
||||
|
||||
@@ -5769,9 +5769,6 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
m_conf.ps.a_masked = 1;
|
||||
m_conf.ps.blend_c = 0;
|
||||
m_conf.require_one_barrier |= true;
|
||||
|
||||
// Alpha write is masked, by default this is enabled on vk/gl but not on dx11/12 as copies are slow so we can enable it now since rt alpha is read.
|
||||
DATE_BARRIER = DATE;
|
||||
}
|
||||
else
|
||||
blend_ad_alpha_masked = false;
|
||||
@@ -7666,21 +7663,6 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
if ((!IsOpaque() || m_context->ALPHA.IsBlack()) && rt && ((m_conf.colormask.wrgba & 0x7) || (m_texture_shuffle && !m_copy_16bit_to_target_shuffle && !m_same_group_texture_shuffle)))
|
||||
{
|
||||
EmulateBlending(blend_alpha_min, blend_alpha_max, DATE, DATE_PRIMID, DATE_BARRIER, rt, can_scale_rt_alpha, new_scale_rt_alpha);
|
||||
|
||||
// Similar to IsRTWritten(), check if the rt will change.
|
||||
const bool no_rt = (!DATE && !m_conf.colormask.wrgba && !m_channel_shuffle);
|
||||
const bool no_ds = !m_conf.ds ||
|
||||
// Depth will be written through the RT.
|
||||
(!no_rt && m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP && !PRIM->TME && m_cached_ctx.ZBUF.ZMSK == 0 &&
|
||||
(m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) == 0 && m_cached_ctx.TEST.ZTE) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && m_cached_ctx.ZBUF.ZMSK != 0);
|
||||
|
||||
if (no_rt && no_ds)
|
||||
{
|
||||
GL_INS("HW: Late draw cancel EmulateBlending().");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7698,6 +7680,26 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to IsRTWritten(), check if the rt will change.
|
||||
const bool no_rt = !rt || !(DATE || m_conf.colormask.wrgba || m_channel_shuffle);
|
||||
const bool no_ds = !ds ||
|
||||
// Depth will be written through the RT.
|
||||
(!no_rt && m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP && !PRIM->TME && m_cached_ctx.ZBUF.ZMSK == 0 &&
|
||||
(m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) == 0 && m_cached_ctx.TEST.ZTE) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && m_cached_ctx.ZBUF.ZMSK != 0);
|
||||
|
||||
if (no_rt && no_ds)
|
||||
{
|
||||
GL_INS("HW: Late draw cancel DrawPrims().");
|
||||
return;
|
||||
}
|
||||
|
||||
// Always swap DATE with DATE_BARRIER if we have barriers on when alpha write is masked.
|
||||
// This is always enabled on vk/gl but not on dx11/12 as copies are slow so we can selectively enable it like now.
|
||||
if (DATE && !m_conf.colormask.wa && (m_conf.require_one_barrier || m_conf.require_full_barrier))
|
||||
DATE_BARRIER = true;
|
||||
|
||||
if ((m_conf.ps.tex_is_fb && rt && rt->m_rt_alpha_scale) || (tex && tex->m_from_target && tex->m_target_direct && tex->m_from_target->m_rt_alpha_scale))
|
||||
m_conf.ps.rta_source_correction = 1;
|
||||
|
||||
@@ -7937,7 +7939,8 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
}
|
||||
else if (DATE_one)
|
||||
{
|
||||
if (features.texture_barrier)
|
||||
const bool multidraw_fb_copy = features.multidraw_fb_copy && (m_conf.require_one_barrier || m_conf.require_full_barrier);
|
||||
if (features.texture_barrier || multidraw_fb_copy)
|
||||
{
|
||||
m_conf.require_one_barrier = true;
|
||||
m_conf.ps.date = 5 + m_cached_ctx.TEST.DATM;
|
||||
|
||||
@@ -2663,8 +2663,10 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
for (auto i = list.begin(); i != list.end(); ++i)
|
||||
{
|
||||
Target* t = *i;
|
||||
const bool half_buffer_match = GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && TEX0.TBW == t->m_TEX0.TBW && TEX0.PSM == t->m_TEX0.PSM &&
|
||||
bp == GSLocalMemory::GetStartBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, GSVector4i(0, size.y, size.x, size.y + 1));
|
||||
// Make sure the target is inside the texture
|
||||
if (t->m_TEX0.TBP0 <= bp && bp <= t->m_end_block && t->Inside(bp, TEX0.TBW, TEX0.PSM, GSVector4i::loadh(size)))
|
||||
if (t->m_TEX0.TBP0 <= bp && bp <= t->m_end_block && (half_buffer_match || t->Inside(bp, TEX0.TBW, TEX0.PSM, GSVector4i::loadh(size))))
|
||||
{
|
||||
if (dst && (GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw))
|
||||
continue;
|
||||
|
||||
@@ -124,6 +124,7 @@ namespace GSTextureReplacements
|
||||
|
||||
/// Textures that have been dumped, to save stat() calls.
|
||||
static std::unordered_set<TextureName> s_dumped_textures;
|
||||
static std::mutex s_dumped_textures_mutex;
|
||||
|
||||
/// Lookup map of texture names to replacements, if they exist.
|
||||
static std::unordered_map<TextureName, std::string> s_replacement_texture_filenames;
|
||||
@@ -802,10 +803,13 @@ void GSTextureReplacements::DumpTexture(const GSTextureCache::HashCacheKey& hash
|
||||
{
|
||||
// check if it's been dumped or replaced already
|
||||
const TextureName name(CreateTextureName(hash, level));
|
||||
if (s_dumped_textures.find(name) != s_dumped_textures.end() || s_replacement_texture_filenames.find(name) != s_replacement_texture_filenames.end())
|
||||
return;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(s_dumped_textures_mutex);
|
||||
if (s_dumped_textures.find(name) != s_dumped_textures.end() || s_replacement_texture_filenames.find(name) != s_replacement_texture_filenames.end())
|
||||
return;
|
||||
|
||||
s_dumped_textures.insert(name);
|
||||
s_dumped_textures.insert(name);
|
||||
}
|
||||
|
||||
// already exists on disk?
|
||||
std::string filename(GetDumpFilename(name, level));
|
||||
@@ -842,9 +846,22 @@ void GSTextureReplacements::DumpTexture(const GSTextureCache::HashCacheKey& hash
|
||||
|
||||
void GSTextureReplacements::ClearDumpedTextureList()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(s_dumped_textures_mutex);
|
||||
s_dumped_textures.clear();
|
||||
}
|
||||
|
||||
u32 GSTextureReplacements::GetDumpedTextureCount()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(s_dumped_textures_mutex);
|
||||
return static_cast<u32>(s_dumped_textures.size());
|
||||
}
|
||||
|
||||
u32 GSTextureReplacements::GetLoadedTextureCount()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(s_replacement_texture_cache_mutex);
|
||||
return static_cast<u32>(s_replacement_texture_cache.size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Worker Thread
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -47,6 +47,12 @@ namespace GSTextureReplacements
|
||||
GSTextureCache::SourceRegion region, GSLocalMemory& mem, u32 level);
|
||||
void ClearDumpedTextureList();
|
||||
|
||||
/// Get the number of textures that have been dumped.
|
||||
u32 GetDumpedTextureCount();
|
||||
|
||||
/// Get the number of replacement textures that have been loaded/cached.
|
||||
u32 GetLoadedTextureCount();
|
||||
|
||||
/// Loader will take a filename and interpret the format (e.g. DDS, PNG, etc).
|
||||
using ReplacementTextureLoader = bool (*)(const std::string& filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image);
|
||||
ReplacementTextureLoader GetLoader(const std::string_view filename);
|
||||
|
||||
@@ -407,8 +407,6 @@ public:
|
||||
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2& ds);
|
||||
/// Copy from a position in sTex to the same position in the currently active render encoder using the given fs pipeline and rect
|
||||
void RenderCopy(GSTexture* sTex, id<MTLRenderPipelineState> pipeline, const GSVector4i& rect);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
|
||||
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override;
|
||||
void DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader) override;
|
||||
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
|
||||
@@ -452,6 +450,10 @@ public:
|
||||
|
||||
void RenderImGui(ImDrawData* data);
|
||||
u32 FrameNo() const { return m_frame; }
|
||||
|
||||
protected:
|
||||
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
|
||||
};
|
||||
|
||||
static constexpr bool IsCommandBufferCompleted(MTLCommandBufferStatus status)
|
||||
|
||||
@@ -1600,33 +1600,21 @@ void GSDeviceMTL::RenderCopy(GSTexture* sTex, id<MTLRenderPipelineState> pipelin
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
}
|
||||
|
||||
void GSDeviceMTL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
|
||||
{ @autoreleasepool {
|
||||
|
||||
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
|
||||
|
||||
id<MTLRenderPipelineState> pipeline = m_convert_pipeline[static_cast<int>(shader)];
|
||||
const LoadAction load_action = (cms.wrgba == 0xf) ? LoadAction::DontCareIfFull : LoadAction::Load;
|
||||
id<MTLRenderPipelineState> pipeline;
|
||||
if (HasVariableWriteMask(shader))
|
||||
pipeline = m_convert_pipeline_copy_mask[GetShaderIndexForMask(shader, cms.wrgba)];
|
||||
else
|
||||
pipeline = m_convert_pipeline[static_cast<int>(shader)];
|
||||
pxAssertRel(pipeline, fmt::format("No pipeline for {}", shaderName(shader)).c_str());
|
||||
|
||||
const LoadAction load_action = (ShaderConvertWriteMask(shader) == 0xf) ? LoadAction::DontCareIfFull : LoadAction::Load;
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, pipeline, linear, load_action, nullptr, 0);
|
||||
}}
|
||||
|
||||
void GSDeviceMTL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{ @autoreleasepool {
|
||||
int sel = 0;
|
||||
if (red) sel |= 1;
|
||||
if (green) sel |= 2;
|
||||
if (blue) sel |= 4;
|
||||
if (alpha) sel |= 8;
|
||||
if (shader == ShaderConvert::RTA_CORRECTION) sel |= 16;
|
||||
const int color_sel = sel & 15;
|
||||
|
||||
id<MTLRenderPipelineState> pipeline = m_convert_pipeline_copy_mask[sel];
|
||||
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, pipeline, false, color_sel == 15 ? LoadAction::DontCareIfFull : LoadAction::Load, nullptr, 0);
|
||||
}}
|
||||
|
||||
static_assert(sizeof(DisplayConstantBuffer) == sizeof(GSMTLPresentPSUniform));
|
||||
static_assert(offsetof(DisplayConstantBuffer, SourceRect) == offsetof(GSMTLPresentPSUniform, source_rect));
|
||||
static_assert(offsetof(DisplayConstantBuffer, TargetRect) == offsetof(GSMTLPresentPSUniform, target_rect));
|
||||
@@ -1683,9 +1671,9 @@ void GSDeviceMTL::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_r
|
||||
const u32 end = i * 4;
|
||||
const u32 vertex_count = end - start;
|
||||
const u32 index_count = vertex_count + (vertex_count >> 1); // 6 indices per 4 vertices
|
||||
const int rta_bit = shader == ShaderConvert::RTA_CORRECTION ? 16 : 0;
|
||||
pxAssert(HasVariableWriteMask(shader) || wmask == 0xf);
|
||||
id<MTLRenderPipelineState> new_pipeline = wmask == 0xf ? m_convert_pipeline[static_cast<int>(shader)]
|
||||
: m_convert_pipeline_copy_mask[wmask | rta_bit];
|
||||
: m_convert_pipeline_copy_mask[GetShaderIndexForMask(shader, wmask)];
|
||||
if (new_pipeline != pipeline)
|
||||
{
|
||||
pipeline = new_pipeline;
|
||||
|
||||
@@ -180,8 +180,7 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool buggy_pbo;
|
||||
if (!CheckFeatures(buggy_pbo))
|
||||
if (!CheckFeatures())
|
||||
return false;
|
||||
|
||||
// Store adapter name currently in use
|
||||
@@ -529,7 +528,7 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
// ****************************************************************
|
||||
// Pbo Pool allocation
|
||||
// ****************************************************************
|
||||
if (!buggy_pbo)
|
||||
if (!m_bugs.buggy_pbo)
|
||||
{
|
||||
m_texture_upload_buffer = GLStreamBuffer::Create(GL_PIXEL_UNPACK_BUFFER, TEXTURE_UPLOAD_BUFFER_SIZE);
|
||||
if (m_texture_upload_buffer)
|
||||
@@ -603,12 +602,14 @@ bool GSDeviceOGL::CreateTextureFX()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
|
||||
bool GSDeviceOGL::CheckFeatures()
|
||||
{
|
||||
//bool vendor_id_amd = false;
|
||||
//bool vendor_id_nvidia = false;
|
||||
//bool vendor_id_intel = false;
|
||||
|
||||
memset(&m_bugs, 0, sizeof(m_bugs));
|
||||
|
||||
const char* vendor = (const char*)glGetString(GL_VENDOR);
|
||||
if (std::strstr(vendor, "Advanced Micro Devices") || std::strstr(vendor, "ATI Technologies Inc.") ||
|
||||
std::strstr(vendor, "ATI"))
|
||||
@@ -620,6 +621,7 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
|
||||
{
|
||||
Console.WriteLn(Color_StrongGreen, "GL: NVIDIA GPU detected.");
|
||||
//vendor_id_nvidia = true;
|
||||
m_bugs.broken_blend_coherency = true;
|
||||
}
|
||||
else if (std::strstr(vendor, "Intel"))
|
||||
{
|
||||
@@ -700,8 +702,8 @@ bool GSDeviceOGL::CheckFeatures(bool& buggy_pbo)
|
||||
|
||||
// Don't use PBOs when we don't have ARB_buffer_storage, orphaning buffers probably ends up worse than just
|
||||
// using the normal texture update routines and letting the driver take care of it.
|
||||
buggy_pbo = !GLAD_GL_VERSION_4_4 && !GLAD_GL_ARB_buffer_storage && !GLAD_GL_EXT_buffer_storage;
|
||||
if (buggy_pbo)
|
||||
m_bugs.buggy_pbo = !GLAD_GL_VERSION_4_4 && !GLAD_GL_ARB_buffer_storage && !GLAD_GL_EXT_buffer_storage;
|
||||
if (m_bugs.buggy_pbo)
|
||||
Console.Warning("GL: Not using PBOs for texture uploads because buffer_storage is unavailable.");
|
||||
|
||||
// Give the user the option to disable PBO usage for downloads.
|
||||
@@ -1253,7 +1255,7 @@ GSTexture* GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& are
|
||||
return nullptr;
|
||||
|
||||
GL_PUSH("PrimID Destination Alpha Clear");
|
||||
StretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast<u8>(datm)], false);
|
||||
DoStretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast<u8>(datm)], false);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@@ -1472,31 +1474,20 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
|
||||
dTex->SetState(GSTexture::State::Dirty);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
OMColorMaskSelector cms, ShaderConvert shader, bool linear)
|
||||
{
|
||||
pxAssert(dTex->IsDepthStencil() == HasDepthOutput(shader));
|
||||
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[(int)shader], false, OMColorMaskSelector(ShaderConvertWriteMask(shader)), linear);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)], false, cms, linear);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool linear)
|
||||
void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
const GLProgram& ps, bool linear)
|
||||
{
|
||||
StretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), linear);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), linear);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{
|
||||
OMColorMaskSelector cms;
|
||||
|
||||
cms.wr = red;
|
||||
cms.wg = green;
|
||||
cms.wb = blue;
|
||||
cms.wa = alpha;
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[(int)shader], false, cms, false);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear)
|
||||
void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear)
|
||||
{
|
||||
CommitClear(sTex, true);
|
||||
|
||||
@@ -1816,12 +1807,12 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
|
||||
// Blend with a constant alpha
|
||||
m_merge_obj.ps[1].Bind();
|
||||
m_merge_obj.ps[1].Uniform4fv(0, GSVector4::unorm8(c).v);
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[1], true, OMColorMaskSelector(), linear);
|
||||
DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[1], true, OMColorMaskSelector(), linear);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Blend with 2 * input alpha
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[0], true, OMColorMaskSelector(), linear);
|
||||
DoStretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[0], true, OMColorMaskSelector(), linear);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1836,7 +1827,7 @@ void GSDeviceOGL::DoInterlace(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
||||
m_interlace.ps[static_cast<int>(shader)].Bind();
|
||||
m_interlace.ps[static_cast<int>(shader)].Uniform4fv(0, cb.ZrH.F32);
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)], linear);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_interlace.ps[static_cast<int>(shader)], linear);
|
||||
}
|
||||
|
||||
bool GSDeviceOGL::CompileFXAAProgram()
|
||||
@@ -1875,7 +1866,7 @@ void GSDeviceOGL::DoFXAA(GSTexture* sTex, GSTexture* dTex)
|
||||
const GSVector4 sRect(0, 0, 1, 1);
|
||||
const GSVector4 dRect(0, 0, s.x, s.y);
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, true);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_fxaa.ps, true);
|
||||
}
|
||||
|
||||
bool GSDeviceOGL::CompileShadeBoostProgram()
|
||||
@@ -1909,10 +1900,10 @@ void GSDeviceOGL::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float par
|
||||
const GSVector4 sRect(0, 0, 1, 1);
|
||||
const GSVector4 dRect(0, 0, s.x, s.y);
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, false);
|
||||
DoStretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, false);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm)
|
||||
void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox)
|
||||
{
|
||||
GL_PUSH("DATE First Pass");
|
||||
|
||||
@@ -1933,6 +1924,17 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
|
||||
|
||||
// ia
|
||||
|
||||
const GSVector4 src = GSVector4(bbox) / GSVector4(ds->GetSize()).xyxy();
|
||||
const GSVector4 dst = src * 2.f - 1.f;
|
||||
|
||||
const GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(dst.x, dst.y, 0.0f, 0.0f), GSVector2(src.x, src.y)},
|
||||
{GSVector4(dst.z, dst.y, 0.0f, 0.0f), GSVector2(src.z, src.y)},
|
||||
{GSVector4(dst.x, dst.w, 0.0f, 0.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, dst.w, 0.0f, 0.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
|
||||
IASetVAO(m_vao);
|
||||
IASetVertexBuffer(vertices, 4);
|
||||
IASetPrimitiveTopology(GL_TRIANGLE_STRIP);
|
||||
@@ -2490,18 +2492,8 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
[[fallthrough]];
|
||||
case GSHWDrawConfig::DestinationAlphaMode::Stencil:
|
||||
{
|
||||
const GSVector4 src = GSVector4(config.drawarea) / GSVector4(config.ds->GetSize()).xyxy();
|
||||
const GSVector4 dst = src * 2.f - 1.f;
|
||||
GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(dst.x, dst.y, 0.0f, 0.0f), GSVector2(src.x, src.y)},
|
||||
{GSVector4(dst.z, dst.y, 0.0f, 0.0f), GSVector2(src.z, src.y)},
|
||||
{GSVector4(dst.x, dst.w, 0.0f, 0.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, dst.w, 0.0f, 0.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, vertices, config.datm);
|
||||
}
|
||||
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, config.datm, config.drawarea);
|
||||
break;
|
||||
}
|
||||
|
||||
GSTexture* draw_rt_clone = nullptr;
|
||||
@@ -2575,10 +2567,19 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
SetupPipeline(psel);
|
||||
|
||||
const bool check_barrier = !(config.require_one_barrier && !m_features.texture_barrier);
|
||||
bool rt_hazard_barrier = config.tex && (config.tex == config.ds || config.tex == config.rt);
|
||||
// In Time Crisis:
|
||||
// 1. Fullscreen sprite reads depth and writes alpha (rt_hazard_barrier true from config.ds == config.tex)
|
||||
// 2. Fullscreen sprite writes gray, rta hw blend blends based on dst alpha.
|
||||
// On Nvidia, 2 seems to not pick up the data written by 1 unless we add a second barrier.
|
||||
// Pretty sure GL is supposed to guarantee that the blend unit is coherent with previous pixel write out, so calling this a bug.
|
||||
if (m_bugs.broken_blend_coherency)
|
||||
rt_hazard_barrier |= (psel.ps.IsFeedbackLoop() || psel.ps.blend_c == 1) && GLState::rt == config.rt;
|
||||
if (config.require_one_barrier || !m_features.texture_barrier)
|
||||
rt_hazard_barrier = false; // Already in place or not available
|
||||
|
||||
// Be careful of the rt already being bound and the blend using the RT without a barrier.
|
||||
if (check_barrier && ((config.tex && (config.tex == config.ds || config.tex == config.rt)) || ((psel.ps.IsFeedbackLoop() || psel.ps.blend_c == 1) && GLState::rt == config.rt)))
|
||||
if (rt_hazard_barrier)
|
||||
{
|
||||
// Ensure all depth writes are finished before sampling
|
||||
GL_INS("GL: Texture barrier to flush depth or rt before reading");
|
||||
|
||||
@@ -141,6 +141,12 @@ private:
|
||||
|
||||
std::unique_ptr<GLContext> m_gl_context;
|
||||
|
||||
struct
|
||||
{
|
||||
bool buggy_pbo : 1; ///< Avoid PBOs and just use glTextureSubImage2D with immediate data
|
||||
bool broken_blend_coherency : 1; ///< Issue on Nvidia GPUs where some blend modes don't seem to be properly coherent, see comment in RenderHW
|
||||
} m_bugs;
|
||||
|
||||
bool m_disable_download_pbo = false;
|
||||
|
||||
GLuint m_fbo = 0; // frame buffer container
|
||||
@@ -231,7 +237,7 @@ private:
|
||||
std::string m_shader_tfx_vgs;
|
||||
std::string m_shader_tfx_fs;
|
||||
|
||||
bool CheckFeatures(bool& buggy_pbo);
|
||||
bool CheckFeatures();
|
||||
|
||||
void SetSwapInterval();
|
||||
void DestroyResources();
|
||||
@@ -265,6 +271,10 @@ private:
|
||||
|
||||
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
|
||||
|
||||
protected:
|
||||
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
|
||||
|
||||
public:
|
||||
GSDeviceOGL();
|
||||
virtual ~GSDeviceOGL();
|
||||
@@ -317,10 +327,8 @@ public:
|
||||
// BlitRect *does* mess with GL state, be sure to re-bind.
|
||||
void BlitRect(GSTexture* sTex, const GSVector4i& r, const GSVector2i& dsize, bool at_origin, bool linear);
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear = true);
|
||||
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool linear);
|
||||
void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GLProgram& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear);
|
||||
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear) override;
|
||||
void UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize) override;
|
||||
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM) override;
|
||||
@@ -332,7 +340,7 @@ public:
|
||||
void RenderHW(GSHWDrawConfig& config) override;
|
||||
void SendHWDraw(const GSHWDrawConfig& config, bool one_barrier, bool full_barrier);
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox);
|
||||
|
||||
void IASetVAO(GLuint vao);
|
||||
void IASetPrimitiveTopology(GLenum topology);
|
||||
|
||||
@@ -323,10 +323,11 @@ void GSDrawScanline::CSetupPrim(const GSVertexSW* vertex, const u16* index, cons
|
||||
{
|
||||
if (sel.iip)
|
||||
{
|
||||
constexpr VectorI mask16 = VectorI::cxpr(0xFFFF);
|
||||
#if _M_SSE >= 0x501
|
||||
GSVector4i::storel(&local.d8.c, GSVector4i(dscan.c * step_shift).xzyw().ps32());
|
||||
GSVector4i::storel(&local.d8.c, (GSVector4i(dscan.c * step_shift) & GSVector4i::cast(mask16)).xzyw().pu32());
|
||||
#else
|
||||
local.d4.c = GSVector4i(dscan.c * step_shift).xzyw().ps32();
|
||||
local.d4.c = (GSVector4i(dscan.c * step_shift) & mask16).xzyw().pu32();
|
||||
#endif
|
||||
VectorF dc(dscan.c);
|
||||
|
||||
@@ -335,8 +336,8 @@ void GSDrawScanline::CSetupPrim(const GSVertexSW* vertex, const u16* index, cons
|
||||
|
||||
for (int i = 0; i < vlen; i++)
|
||||
{
|
||||
VectorI r = VectorI(dr * shift[1 + i]).ps32();
|
||||
VectorI b = VectorI(db * shift[1 + i]).ps32();
|
||||
VectorI r = (VectorI(dr * shift[1 + i]) & mask16).pu32();
|
||||
VectorI b = (VectorI(db * shift[1 + i]) & mask16).pu32();
|
||||
|
||||
local.d[i].rb = r.upl16(b);
|
||||
}
|
||||
@@ -346,8 +347,8 @@ void GSDrawScanline::CSetupPrim(const GSVertexSW* vertex, const u16* index, cons
|
||||
|
||||
for (int i = 0; i < vlen; i++)
|
||||
{
|
||||
VectorI g = VectorI(dg * shift[1 + i]).ps32();
|
||||
VectorI a = VectorI(da * shift[1 + i]).ps32();
|
||||
VectorI g = (VectorI(dg * shift[1 + i]) & mask16).pu32();
|
||||
VectorI a = (VectorI(da * shift[1 + i]) & mask16).pu32();
|
||||
|
||||
local.d[i].ga = g.upl16(a);
|
||||
}
|
||||
|
||||
@@ -1549,7 +1549,7 @@ void GSRasterizerList::Queue(const GSRingHeap::SharedPtr<GSRasterizerData>& data
|
||||
pxAssert(r.top >= 0 && r.top < 2048 && r.bottom >= 0 && r.bottom < 2048);
|
||||
|
||||
int top = r.top >> m_thread_height;
|
||||
int bottom = std::min<int>((r.bottom + (1 << m_thread_height) - 1) >> m_thread_height, top + m_workers.size());
|
||||
int bottom = std::min<int>((r.bottom + (1 << m_thread_height) - 1) >> m_thread_height, top + (int)m_workers.size());
|
||||
|
||||
while (top < bottom)
|
||||
{
|
||||
|
||||
@@ -1652,7 +1652,7 @@ void GSRendererSW::SharedData::UpdateSource()
|
||||
|
||||
std::string s;
|
||||
|
||||
for (size_t i = 0; m_tex[i].t; i++)
|
||||
for (u32 i = 0; m_tex[i].t; i++)
|
||||
{
|
||||
const GIFRegTEX0& TEX0 = g_gs_renderer->GetTex0Layer(i);
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ void GSSetupPrimCodeGenerator::Generate()
|
||||
many_regs = isYmm && !m_sel.notest && needs_shift;
|
||||
|
||||
#ifdef _WIN64
|
||||
int needs_saving = many_regs ? 6 : m_sel.notest ? 0 : 2;
|
||||
int needs_saving = many_regs ? 7 : m_sel.notest ? 1 : 3;
|
||||
if (needs_saving)
|
||||
{
|
||||
sub(rsp, 8 + 16 * needs_saving);
|
||||
@@ -398,12 +398,17 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
|
||||
broadcastf128(xym0, ptr[_dscan + offsetof(GSVertexSW, c)]);
|
||||
|
||||
// m_local.d4.c = GSVector4i(c * 4.0f).xzyw().ps32();
|
||||
// constexpr VectorI mask16 = VectorI::cxpr(0xFFFF);
|
||||
XYm mask16 = XYm(many_regs ? 12 : m_sel.notest ? 6 : 8);
|
||||
pcmpeqd(mask16, mask16);
|
||||
psrld(mask16, 16);
|
||||
|
||||
// local.d4.c = (GSVector4i(dscan.c * step_shift) & mask16).xzyw().pu32();
|
||||
THREEARG(mulps, xmm1, xmm0, xmm3);
|
||||
cvttps2dq(xmm1, xmm1);
|
||||
pshufd(xmm1, xmm1, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
packssdw(xmm1, xmm1);
|
||||
pand(xym1, mask16);
|
||||
packusdw(xmm1, xmm1);
|
||||
if (isXmm)
|
||||
movdqa(_rip_local_d(c), xmm1);
|
||||
else
|
||||
@@ -419,23 +424,25 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
|
||||
for (int i = 0; i < (m_sel.notest ? 1 : dsize); i++)
|
||||
{
|
||||
// GSVector4i r = GSVector4i(dr * m_shift[i]).ps32();
|
||||
// VectorI r = (VectorI(dr * shift[1 + i]) & mask16).pu32();
|
||||
|
||||
if (i < 4 || many_regs)
|
||||
THREEARG(mulps, xym0, XYm(4 + i), xym2);
|
||||
else
|
||||
vmulps(ymm0, ymm2, ptr[g_const.m_shift_256b[i + 1]]);
|
||||
cvttps2dq(xym0, xym0);
|
||||
packssdw(xym0, xym0);
|
||||
pand(xym0, mask16);
|
||||
packusdw(xym0, xym0);
|
||||
|
||||
// GSVector4i b = GSVector4i(db * m_shift[i]).ps32();
|
||||
// VectorI b = (VectorI(db * shift[1 + i]) & mask16).pu32();
|
||||
|
||||
if (i < 4 || many_regs)
|
||||
THREEARG(mulps, xym1, XYm(4 + i), xym3);
|
||||
else
|
||||
vmulps(ymm1, ymm3, ptr[g_const.m_shift_256b[i + 1]]);
|
||||
cvttps2dq(xym1, xym1);
|
||||
packssdw(xym1, xym1);
|
||||
pand(xym1, mask16);
|
||||
packusdw(xym1, xym1);
|
||||
|
||||
// m_local.d[i].rb = r.upl16(b);
|
||||
|
||||
@@ -455,23 +462,25 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
|
||||
for (int i = 0; i < (m_sel.notest ? 1 : dsize); i++)
|
||||
{
|
||||
// GSVector4i g = GSVector4i(dg * m_shift[i]).ps32();
|
||||
// VectorI g = (VectorI(dg * shift[1 + i]) & mask16).pu32();
|
||||
|
||||
if (i < 4 || many_regs)
|
||||
THREEARG(mulps, xym0, XYm(4 + i), xym2);
|
||||
else
|
||||
vmulps(ymm0, ymm2, ptr[g_const.m_shift_256b[i + 1]]);
|
||||
cvttps2dq(xym0, xym0);
|
||||
packssdw(xym0, xym0);
|
||||
pand(xym0, mask16);
|
||||
packusdw(xym0, xym1);
|
||||
|
||||
// GSVector4i a = GSVector4i(da * m_shift[i]).ps32();
|
||||
// VectorI a = (VectorI(da * shift[1 + i]) & mask16).pu32();
|
||||
|
||||
if (i < 4 || many_regs)
|
||||
THREEARG(mulps, xym1, XYm(4 + i), xym3);
|
||||
else
|
||||
vmulps(ymm1, ymm3, ptr[g_const.m_shift_256b[i + 1]]);
|
||||
cvttps2dq(xym1, xym1);
|
||||
packssdw(xym1, xym1);
|
||||
pand(xym1, mask16);
|
||||
packusdw(xym1, xym1);
|
||||
|
||||
// m_local.d[i].ga = g.upl16(a);
|
||||
|
||||
|
||||
@@ -225,14 +225,13 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
// GSVector4 c = dscan.c;
|
||||
armAsm->Ldr(v16, MemOperand(_dscan, offsetof(GSVertexSW, c)));
|
||||
|
||||
// m_local.d4.c = GSVector4i(c * 4.0f).xzyw().ps32();
|
||||
|
||||
// GSVector4i tmp = GSVector4i(dscan.c * step_shift).xzyw();
|
||||
// local.d4.c = tmp.uzp1_16(tmp); // Not currently in GSVector since that's mainly targeting x86 for now
|
||||
armAsm->Fmul(v2.V4S(), v16.V4S(), v3.V4S());
|
||||
armAsm->Fcvtzs(v2.V4S(), v2.V4S());
|
||||
armAsm->Rev64(_vscratch.V4S(), v2.V4S());
|
||||
armAsm->Uzp1(v2.V4S(), v2.V4S(), _vscratch.V4S());
|
||||
armAsm->Sqxtn(v2.V4H(), v2.V4S());
|
||||
armAsm->Dup(v2.V2D(), v2.V2D(), 0);
|
||||
armAsm->Uzp1(v2.V8H(), v2.V8H(), v2.V8H());
|
||||
armAsm->Str(v2, MemOperand(_locals, offsetof(GSScanlineLocalData, d4.c)));
|
||||
|
||||
// GSVector4 dr = c.xxxx();
|
||||
@@ -243,23 +242,18 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
|
||||
for (int i = 0; i < (m_sel.notest ? 1 : 4); i++)
|
||||
{
|
||||
// GSVector4i r = GSVector4i(dr * m_shift[i]).ps32();
|
||||
// VectorI r = VectorI(dr * shift[1 + i]);
|
||||
|
||||
armAsm->Fmul(v2.V4S(), v0.V4S(), VRegister(4 + i, kFormat4S));
|
||||
armAsm->Fcvtzs(v2.V4S(), v2.V4S());
|
||||
armAsm->Sqxtn(v2.V4H(), v2.V4S());
|
||||
armAsm->Dup(v2.V2D(), v2.V2D(), 0);
|
||||
|
||||
// GSVector4i b = GSVector4i(db * m_shift[i]).ps32();
|
||||
// VectorI b = VectorI(db * shift[1 + i]);
|
||||
|
||||
armAsm->Fmul(v3.V4S(), v1.V4S(), VRegister(4 + i, kFormat4S));
|
||||
armAsm->Fcvtzs(v3.V4S(), v3.V4S());
|
||||
armAsm->Sqxtn(v3.V4H(), v3.V4S());
|
||||
armAsm->Dup(v3.V2D(), v3.V2D(), 0);
|
||||
|
||||
// m_local.d[i].rb = r.upl16(b);
|
||||
|
||||
armAsm->Zip1(v2.V8H(), v2.V8H(), v3.V8H());
|
||||
// m_local.d[i].rb = r.trn1_16(b); // Not currently in GSVector since that's mainly targeting x86 for now
|
||||
armAsm->Trn1(v2.V8H(), v2.V8H(), v3.V8H());
|
||||
armAsm->Str(v2, _local(d[i].rb));
|
||||
}
|
||||
|
||||
@@ -273,23 +267,19 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
|
||||
for (int i = 0; i < (m_sel.notest ? 1 : 4); i++)
|
||||
{
|
||||
// GSVector4i g = GSVector4i(dg * m_shift[i]).ps32();
|
||||
// VectorI g = VectorI(dg * shift[1 + i]);
|
||||
|
||||
armAsm->Fmul(v2.V4S(), v0.V4S(), VRegister(4 + i, kFormat4S));
|
||||
armAsm->Fcvtzs(v2.V4S(), v2.V4S());
|
||||
armAsm->Sqxtn(v2.V4H(), v2.V4S());
|
||||
armAsm->Dup(v2.V2D(), v2.V2D(), 0);
|
||||
|
||||
// GSVector4i a = GSVector4i(da * m_shift[i]).ps32();
|
||||
// VectorI a = VectorI(da * shift[1 + i]);
|
||||
|
||||
armAsm->Fmul(v3.V4S(), v1.V4S(), VRegister(4 + i, kFormat4S));
|
||||
armAsm->Fcvtzs(v3.V4S(), v3.V4S());
|
||||
armAsm->Sqxtn(v3.V4H(), v3.V4S());
|
||||
armAsm->Dup(v3.V2D(), v3.V2D(), 0);
|
||||
|
||||
// m_local.d[i].ga = g.upl16(a);
|
||||
// m_local.d[i].ga = g.trn1_16(a); // Not currently in GSVector since that's mainly targeting x86 for now
|
||||
|
||||
armAsm->Zip1(v2.V8H(), v2.V8H(), v3.V8H());
|
||||
armAsm->Trn1(v2.V8H(), v2.V8H(), v3.V8H());
|
||||
armAsm->Str(v2, _local(d[i].ga));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2821,31 +2821,16 @@ void GSDeviceVK::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
||||
dTexVK->SetState(GSTexture::State::Dirty);
|
||||
}
|
||||
|
||||
void GSDeviceVK::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
ShaderConvert shader /* = ShaderConvert::COPY */, bool linear /* = true */)
|
||||
void GSDeviceVK::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear)
|
||||
{
|
||||
pxAssert(HasDepthOutput(shader) == (dTex && dTex->GetType() == GSTexture::Type::DepthStencil));
|
||||
pxAssert(linear ? SupportsBilinear(shader) : SupportsNearest(shader));
|
||||
|
||||
GL_INS("StretchRect(%d) {%d,%d} %dx%d -> {%d,%d) %dx%d", shader, int(sRect.left), int(sRect.top),
|
||||
int(sRect.right - sRect.left), int(sRect.bottom - sRect.top), int(dRect.left), int(dRect.top),
|
||||
int(dRect.right - dRect.left), int(dRect.bottom - dRect.top));
|
||||
|
||||
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect,
|
||||
dTex ? m_convert[static_cast<int>(shader)] : m_present[static_cast<int>(shader)], linear,
|
||||
ShaderConvertWriteMask(shader) == 0xf);
|
||||
}
|
||||
|
||||
void GSDeviceVK::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
|
||||
bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{
|
||||
GL_PUSH("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", red, green, blue, alpha);
|
||||
|
||||
const u32 index = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
|
||||
const bool allow_discard = (index == 0xf);
|
||||
int rta_offset = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
|
||||
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect, m_color_copy[index + rta_offset],
|
||||
false, allow_discard);
|
||||
const bool allow_discard = (cms.wrgba == 0xf);
|
||||
VkPipeline state;
|
||||
if (HasVariableWriteMask(shader))
|
||||
state = m_color_copy[GetShaderIndexForMask(shader, cms.wrgba)];
|
||||
else
|
||||
state = dTex ? m_convert[static_cast<int>(shader)] : m_present[static_cast<int>(shader)];
|
||||
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect, state, linear, allow_discard);
|
||||
}
|
||||
|
||||
void GSDeviceVK::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
@@ -2967,10 +2952,10 @@ void GSDeviceVK::DoMultiStretchRects(
|
||||
BeginRenderPassForStretchRect(dTex, rc, rc, false);
|
||||
SetUtilityTexture(rects[0].src, rects[0].linear ? m_linear_sampler : m_point_sampler);
|
||||
|
||||
pxAssert(shader == ShaderConvert::COPY || shader == ShaderConvert::RTA_CORRECTION || rects[0].wmask.wrgba == 0xf);
|
||||
int rta_bit = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
|
||||
SetPipeline(
|
||||
(rects[0].wmask.wrgba != 0xf) ? m_color_copy[rects[0].wmask.wrgba | rta_bit] : m_convert[static_cast<int>(shader)]);
|
||||
pxAssert(HasVariableWriteMask(shader) || rects[0].wmask.wrgba == 0xf);
|
||||
SetPipeline((rects[0].wmask.wrgba != 0xf) ?
|
||||
m_color_copy[GetShaderIndexForMask(shader, rects[0].wmask.wrgba)] :
|
||||
m_convert[static_cast<int>(shader)]);
|
||||
|
||||
if (ApplyUtilityState())
|
||||
DrawIndexedPrimitive();
|
||||
|
||||
@@ -470,6 +470,10 @@ private:
|
||||
|
||||
void DestroyResources();
|
||||
|
||||
protected:
|
||||
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
GSHWDrawConfig::ColorMaskSelector cms, ShaderConvert shader, bool linear) override;
|
||||
|
||||
public:
|
||||
GSDeviceVK();
|
||||
~GSDeviceVK() override;
|
||||
@@ -525,10 +529,6 @@ public:
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
|
||||
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
ShaderConvert shader = ShaderConvert::COPY, bool linear = true) override;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red,
|
||||
bool green, bool blue, bool alpha, ShaderConvert shader = ShaderConvert::COPY) override;
|
||||
void PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
PresentShader shader, float shaderTime, bool linear) override;
|
||||
void DrawMultiStretchRects(
|
||||
|
||||
@@ -521,7 +521,7 @@ struct Gif_Path
|
||||
// GS Packets that MTGS hasn't yet processed
|
||||
u32 GetPendingGSPackets()
|
||||
{
|
||||
return mtvu.gsPackQueue.size();
|
||||
return (u32)mtvu.gsPackQueue.size();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "SIO/Memcard/MemoryCardFile.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Error.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/Timer.h"
|
||||
@@ -103,7 +104,10 @@ static void HotkeyLoadStateSlot(s32 slot)
|
||||
return;
|
||||
}
|
||||
|
||||
VMManager::LoadStateFromSlot(slot);
|
||||
Error error;
|
||||
if (!VMManager::LoadStateFromSlot(slot, false, &error))
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
error.GetDescription(), Host::OSD_INFO_DURATION);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4198,7 +4198,7 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
|
||||
MenuHeading(FSUI_CSTR("On-Screen Display"));
|
||||
DrawIntSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_MAGNIFYING_GLASS, "OSD Scale"),
|
||||
FSUI_CSTR("Determines how large the on-screen messages and monitor are."), "EmuCore/GS", "OsdScale", 100, 25, 500, 1, FSUI_CSTR("%d%%"));
|
||||
FSUI_CSTR("Determines how large the on-screen messages and monitors are."), "EmuCore/GS", "OsdScale", 100, 25, 500, 1, FSUI_CSTR("%d%%"));
|
||||
|
||||
// OSD Positioning Options
|
||||
static constexpr const char* s_osd_position_options[] = {
|
||||
@@ -4216,45 +4216,44 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
static constexpr const char* s_osd_position_values[] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
};
|
||||
|
||||
|
||||
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_COMMENT, "OSD Messages Position"),
|
||||
FSUI_CSTR("Determines where on-screen display messages are positioned."), "EmuCore/GS", "OsdMessagesPos", "1",
|
||||
s_osd_position_options, s_osd_position_values, std::size(s_osd_position_options), true);
|
||||
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_CHART_BAR, "OSD Performance Position"),
|
||||
FSUI_CSTR("Determines where performance statistics are positioned."), "EmuCore/GS", "OsdPerformancePos", "3",
|
||||
s_osd_position_options, s_osd_position_values, std::size(s_osd_position_options), true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_INFO, "Show PCSX2 Version"),
|
||||
FSUI_CSTR("Shows the current PCSX2 version on the top-right corner of the display."), "EmuCore/GS",
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CODE_MERGE, "Show PCSX2 Version"),
|
||||
FSUI_CSTR("Shows the current PCSX2 version."), "EmuCore/GS",
|
||||
"OsdShowVersion", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GAUGE_SIMPLE_HIGH, "Show Speed"),
|
||||
FSUI_CSTR("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."), "EmuCore/GS",
|
||||
FSUI_CSTR("Shows the current emulation speed of the system as a percentage."), "EmuCore/GS",
|
||||
"OsdShowSpeed", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_IMAGES, "Show FPS"),
|
||||
FSUI_CSTR(
|
||||
"Shows the number of video frames (or v-syncs) displayed per second by the system in the top-right corner of the display."),
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FILM, "Show FPS"),
|
||||
FSUI_CSTR("Shows the number of internal video frames displayed per second by the system."),
|
||||
"EmuCore/GS", "OsdShowFPS", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_MICROCHIP_ALT, "Show CPU Usage"),
|
||||
FSUI_CSTR("Shows the CPU usage based on threads in the top-right corner of the display."), "EmuCore/GS", "OsdShowCPU", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_IMAGE, "Show GPU Usage"),
|
||||
FSUI_CSTR("Shows the host's GPU usage in the top-right corner of the display."), "EmuCore/GS", "OsdShowGPU", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CLAPPERBOARD, "Show VPS"),
|
||||
FSUI_CSTR("Shows the number of V-syncs performed per second by the system."), "EmuCore/GS", "OsdShowVPS", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_MONITOR_CODE, "Show Resolution"),
|
||||
FSUI_CSTR("Shows the resolution of the game in the top-right corner of the display."), "EmuCore/GS",
|
||||
"OsdShowResolution", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_HEART_PULSE, "Show GS Statistics"),
|
||||
FSUI_CSTR("Shows statistics about GS (primitives, draw calls) in the top-right corner of the display."), "EmuCore/GS",
|
||||
"OsdShowGSStats", false);
|
||||
FSUI_CSTR("Shows the internal resolution of the game."), "EmuCore/GS", "OsdShowResolution", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_COMPUTER, "Show Hardware Info"),
|
||||
FSUI_CSTR("Shows the current system CPU and GPU information."), "EmuCore/GS", "OsdShowHardwareInfo", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CHART_PIE, "Show GS Statistics"),
|
||||
FSUI_CSTR("Shows statistics about the emulated GS such as primitives and draw calls."),
|
||||
"EmuCore/GS", "OsdShowGSStats", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_MICROCHIP_ALT, "Show CPU Usage"),
|
||||
FSUI_CSTR("Shows the host's CPU utilization based on threads."), "EmuCore/GS", "OsdShowCPU", false);
|
||||
// TODO: Change this to a GPU icon when FA gets one or PromptFont fixes their codepoints.
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_IMAGE, "Show GPU Usage"),
|
||||
FSUI_CSTR("Shows the host's GPU utilization."), "EmuCore/GS", "OsdShowGPU", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_PLAY, "Show Status Indicators"),
|
||||
FSUI_CSTR("Shows indicators when fast forwarding, pausing, and other abnormal states are active."), "EmuCore/GS",
|
||||
"OsdShowIndicators", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_KEYBOARD, "Show Input Recording Status"),
|
||||
FSUI_CSTR("Shows the currently active input recording status."), "EmuCore/GS",
|
||||
"OsdShowInputRec", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_VIDEO, "Show Video Capture Status"),
|
||||
FSUI_CSTR("Shows the currently active video capture status."), "EmuCore/GS",
|
||||
"OsdShowVideoCapture", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_HEARTBEAT_ALT, "Show Frame Times"),
|
||||
FSUI_CSTR("Shows a visual history of frame times."), "EmuCore/GS", "OsdShowFrameTimes", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_SLIDERS, "Show Settings"),
|
||||
FSUI_CSTR("Shows the current configuration in the bottom-right corner of the display."), "EmuCore/GS", "OsdShowSettings", false);
|
||||
|
||||
FSUI_CSTR("Shows the current configuration in the bottom-right corner of the display."),
|
||||
"EmuCore/GS", "OsdShowSettings", false);
|
||||
bool show_settings = (bsi->GetBoolValue("EmuCore/GS", "OsdShowSettings", false) == false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_HAMMER, "Show Patches"),
|
||||
FSUI_CSTR("Shows the amount of currently active patches/cheats on the bottom-right corner of the display."), "EmuCore/GS",
|
||||
@@ -4262,12 +4261,15 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_GAMEPAD_ALT, "Show Inputs"),
|
||||
FSUI_CSTR("Shows the current controller state of the system in the bottom-left corner of the display."), "EmuCore/GS",
|
||||
"OsdShowInputs", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_HEARTBEAT_ALT, "Show Frame Times"),
|
||||
FSUI_CSTR("Shows a visual history of frame times in the upper-left corner of the display."), "EmuCore/GS", "OsdShowFrameTimes",
|
||||
false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_PF_MONITOR_CODE, "Show Hardware Info"),
|
||||
FSUI_CSTR("Shows the current system hardware information on the OSD."), "EmuCore/GS", "OsdShowHardwareInfo",
|
||||
false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_VIDEO, "Show Video Capture Status"),
|
||||
FSUI_CSTR("Shows the status of the currently active video capture."), "EmuCore/GS",
|
||||
"OsdShowVideoCapture", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_KEYBOARD, "Show Input Recording Status"),
|
||||
FSUI_CSTR("Shows the status of the currently active input recording."), "EmuCore/GS",
|
||||
"OsdShowInputRec", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_IMAGES, "Show Texture Replacement Status"),
|
||||
FSUI_CSTR("Shows the number of dumped and loaded texture replacements on the OSD."), "EmuCore/GS",
|
||||
"OsdShowTextureReplacements", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TRIANGLE_EXCLAMATION, "Warn About Unsafe Settings"),
|
||||
FSUI_CSTR("Displays warnings when settings are enabled which may break games."), "EmuCore", "WarnAboutUnsafeSettings", true);
|
||||
|
||||
@@ -6866,6 +6868,46 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
|
||||
BeginMenuButtons(submenu_item_count[static_cast<u32>(s_current_pause_submenu)], 1.0f, ImGuiFullscreen::LAYOUT_MENU_BUTTON_X_PADDING,
|
||||
ImGuiFullscreen::LAYOUT_MENU_BUTTON_Y_PADDING, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
||||
|
||||
if (!ImGui::IsPopupOpen(0u, ImGuiPopupFlags_AnyPopup))
|
||||
{
|
||||
const bool up_pressed = ImGui::IsKeyPressed(ImGuiKey_GamepadDpadUp, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) ||
|
||||
ImGui::IsKeyPressed(ImGuiKey_UpArrow, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
|
||||
const bool down_pressed = ImGui::IsKeyPressed(ImGuiKey_GamepadDpadDown, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner) ||
|
||||
ImGui::IsKeyPressed(ImGuiKey_DownArrow, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner);
|
||||
|
||||
if (up_pressed || down_pressed)
|
||||
{
|
||||
const ImGuiID current_focus_id = ImGui::GetFocusID();
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
ImGuiID first_id = 0;
|
||||
ImGuiID last_id = 0;
|
||||
|
||||
switch (s_current_pause_submenu)
|
||||
{
|
||||
case PauseSubMenu::None:
|
||||
first_id = ImGui::GetID(FSUI_ICONSTR(ICON_FA_PLAY, "Resume Game"));
|
||||
last_id = ImGui::GetID(FSUI_ICONSTR(ICON_FA_POWER_OFF, "Close Game"));
|
||||
break;
|
||||
case PauseSubMenu::Exit:
|
||||
first_id = ImGui::GetID(FSUI_ICONSTR(ICON_PF_BACKWARD, "Back To Pause Menu"));
|
||||
last_id = ImGui::GetID(FSUI_ICONSTR(ICON_FA_POWER_OFF, "Exit Without Saving"));
|
||||
break;
|
||||
case PauseSubMenu::Achievements:
|
||||
first_id = ImGui::GetID(FSUI_ICONSTR(ICON_PF_BACKWARD, "Back To Pause Menu"));
|
||||
last_id = ImGui::GetID(FSUI_ICONSTR(ICON_FA_STOPWATCH, "Leaderboards"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (first_id != 0 && last_id != 0)
|
||||
{
|
||||
if (up_pressed && current_focus_id == first_id)
|
||||
ImGui::SetFocusID(last_id, window);
|
||||
else if (down_pressed && current_focus_id == last_id)
|
||||
ImGui::SetFocusID(first_id, window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (s_current_pause_submenu)
|
||||
{
|
||||
case PauseSubMenu::None:
|
||||
@@ -7562,65 +7604,17 @@ void FullscreenUI::DrawResumeStateSelector()
|
||||
|
||||
void FullscreenUI::DoLoadState(std::string path)
|
||||
{
|
||||
// Check for hardcore mode before loading state
|
||||
if (Achievements::IsHardcoreModeActive())
|
||||
{
|
||||
Achievements::ConfirmHardcoreModeDisableAsync(TRANSLATE("VMManager", "Loading state"),
|
||||
[path = std::move(path)](bool approved) {
|
||||
if (approved)
|
||||
DoLoadState(std::move(path));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string filename = std::string(Path::GetFileName(path));
|
||||
s32 slot = -1;
|
||||
bool is_backup = false;
|
||||
|
||||
std::string base_filename = filename;
|
||||
if (filename.length() > 7 && filename.substr(filename.length() - 7) == ".backup")
|
||||
{
|
||||
is_backup = true;
|
||||
base_filename = filename.substr(0, filename.length() - 7);
|
||||
}
|
||||
|
||||
// Get slot number from filename (format: serial.crc.slot.p2s)
|
||||
const size_t last_dot = base_filename.rfind('.');
|
||||
const size_t second_last_dot = base_filename.rfind('.', last_dot - 1);
|
||||
if (last_dot != std::string::npos && second_last_dot != std::string::npos)
|
||||
{
|
||||
const std::string slot_str = base_filename.substr(second_last_dot + 1, last_dot - second_last_dot - 1);
|
||||
if (!slot_str.empty())
|
||||
slot = std::atoi(slot_str.c_str());
|
||||
}
|
||||
|
||||
const std::string message = (slot >= 0) ?
|
||||
fmt::format(TRANSLATE_FS("VMManager", "Loading {} from slot {}..."), is_backup ? TRANSLATE("VMManager", "backup state") : TRANSLATE("VMManager", "state"), slot) :
|
||||
TRANSLATE_STR("VMManager", "Loading save state...");
|
||||
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_FOLDER_OPEN, message, Host::OSD_QUICK_DURATION);
|
||||
|
||||
Host::RunOnCPUThread([path = std::move(path)]()
|
||||
{
|
||||
const std::string boot_path = s_save_state_selector_game_path;
|
||||
Host::RunOnCPUThread([boot_path = s_save_state_selector_game_path, path = std::move(path)]() {
|
||||
if (VMManager::HasValidVM())
|
||||
{
|
||||
Error error;
|
||||
if (!SaveState_UnzipFromDisk(path, &error))
|
||||
if (!VMManager::LoadState(path.c_str(), &error))
|
||||
{
|
||||
if (error.GetDescription().find("outdated") != std::string::npos)
|
||||
{
|
||||
Host::RunOnCPUThread([error_desc = error.GetDescription()]()
|
||||
{
|
||||
ImGuiFullscreen::OpenInfoMessageDialog(
|
||||
FSUI_ICONSTR(ICON_FA_TRIANGLE_EXCLAMATION, "Incompatible Save State"),
|
||||
error_desc);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("VMManager", "Failed to load save state"), error.GetDescription());
|
||||
}
|
||||
MTGS::RunOnGSThread([error = std::move(error)]() {
|
||||
ImGuiFullscreen::OpenInfoMessageDialog(
|
||||
FSUI_ICONSTR(ICON_FA_TRIANGLE_EXCLAMATION, "Failed to Load State"),
|
||||
error.GetDescription());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10113,6 +10107,10 @@ TRANSLATE_NOOP("FullscreenUI", "Compression Method");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Compression Level");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Debug Device");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Resume Game");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Close Game");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Back To Pause Menu");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Exit Without Saving");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Leaderboards");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Toggle Frame Limit");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Game Properties");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Achievements");
|
||||
@@ -10120,16 +10118,12 @@ TRANSLATE_NOOP("FullscreenUI", "Save Screenshot");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Switch To Software Renderer");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Switch To Hardware Renderer");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Change Disc");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Close Game");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Exit Without Saving");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Back To Pause Menu");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Exit And Save State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Leaderboards");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Delete Save");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Close Menu");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Default Boot");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Delete State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Incompatible Save State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Load State");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Full Boot");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Reset Play Time");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Confirm Reset");
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "GS/GSCapture.h"
|
||||
#include "GS/GSVector.h"
|
||||
#include "GS/Renderers/Common/GSDevice.h"
|
||||
#include "GS/Renderers/HW/GSTextureReplacements.h"
|
||||
#include "Host.h"
|
||||
#include "IconsFontAwesome6.h"
|
||||
#include "IconsPromptFont.h"
|
||||
@@ -28,6 +29,7 @@
|
||||
#include "VMManager.h"
|
||||
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/Error.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/StringUtil.h"
|
||||
@@ -147,6 +149,7 @@ namespace ImGuiManager
|
||||
static void DrawInputsOverlay(float scale, float margin, float spacing);
|
||||
static void DrawInputRecordingOverlay(float& position_y, float scale, float margin, float spacing);
|
||||
static void DrawVideoCaptureOverlay(float& position_y, float scale, float margin, float spacing);
|
||||
static void DrawTextureReplacementsOverlay(float& position_y, float scale, float margin, float spacing);
|
||||
} // namespace ImGuiManager
|
||||
|
||||
static std::tuple<float, float> GetMinMax(std::span<const float> values)
|
||||
@@ -622,7 +625,7 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
else
|
||||
APPEND("IR={} ", static_cast<unsigned>(GSConfig.UpscaleMultiplier));
|
||||
|
||||
APPEND("B={} PL={} ", static_cast<unsigned>(GSConfig.AccurateBlendingUnit), static_cast<unsigned>(GSConfig.TexturePreloading));
|
||||
APPEND("BL={} TPL={} ", static_cast<unsigned>(GSConfig.AccurateBlendingUnit), static_cast<unsigned>(GSConfig.TexturePreloading));
|
||||
if (GSConfig.GPUPaletteConversion)
|
||||
APPEND("PLTX ");
|
||||
|
||||
@@ -945,6 +948,46 @@ __ri void ImGuiManager::DrawVideoCaptureOverlay(float& position_y, float scale,
|
||||
position_y += std::max(icon_size.y, text_size.y) + spacing;
|
||||
}
|
||||
|
||||
__ri void ImGuiManager::DrawTextureReplacementsOverlay(float& position_y, float scale, float margin, float spacing)
|
||||
{
|
||||
if (!GSConfig.OsdShowTextureReplacements ||
|
||||
FullscreenUI::HasActiveWindow())
|
||||
return;
|
||||
|
||||
const bool dumping_active = GSConfig.DumpReplaceableTextures;
|
||||
const bool replacement_active = GSConfig.LoadTextureReplacements;
|
||||
|
||||
if (!dumping_active && !replacement_active)
|
||||
return;
|
||||
|
||||
const float shadow_offset = std::ceil(scale);
|
||||
ImFont* const standard_font = ImGuiManager::GetStandardFont();
|
||||
const float font_size = ImGuiManager::GetFontSizeStandard();
|
||||
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
||||
|
||||
SmallString texture_line;
|
||||
if (replacement_active)
|
||||
{
|
||||
const u32 loaded_count = GSTextureReplacements::GetLoadedTextureCount();
|
||||
texture_line.format("{} Replaced: {}", ICON_FA_IMAGES, loaded_count);
|
||||
}
|
||||
if (dumping_active)
|
||||
{
|
||||
if (!texture_line.empty())
|
||||
texture_line.append(" | ");
|
||||
const u32 dumped_count = GSTextureReplacements::GetDumpedTextureCount();
|
||||
texture_line.append_format("{} Dumped: {}", ICON_FA_DOWNLOAD, dumped_count);
|
||||
}
|
||||
|
||||
ImVec2 text_size = standard_font->CalcTextSizeA(font_size, std::numeric_limits<float>::max(), -1.0f, texture_line.c_str(), nullptr, nullptr);
|
||||
const ImVec2 text_pos(GetWindowWidth() - margin - text_size.x, position_y);
|
||||
|
||||
dl->AddText(standard_font, font_size, ImVec2(text_pos.x + shadow_offset, text_pos.y + shadow_offset), IM_COL32(0, 0, 0, 100), texture_line.c_str());
|
||||
dl->AddText(standard_font, font_size, text_pos, white_color, texture_line.c_str());
|
||||
|
||||
position_y += text_size.y + spacing;
|
||||
}
|
||||
|
||||
namespace SaveStateSelectorUI
|
||||
{
|
||||
namespace
|
||||
@@ -1325,7 +1368,10 @@ s32 SaveStateSelectorUI::GetCurrentSlot()
|
||||
void SaveStateSelectorUI::LoadCurrentSlot()
|
||||
{
|
||||
Host::RunOnCPUThread([slot = GetCurrentSlot()]() {
|
||||
VMManager::LoadStateFromSlot(slot);
|
||||
Error error;
|
||||
if (!VMManager::LoadStateFromSlot(slot, false, &error))
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
error.GetDescription(), Host::OSD_INFO_DURATION);
|
||||
});
|
||||
Close();
|
||||
}
|
||||
@@ -1333,7 +1379,10 @@ void SaveStateSelectorUI::LoadCurrentSlot()
|
||||
void SaveStateSelectorUI::LoadCurrentBackupSlot()
|
||||
{
|
||||
Host::RunOnCPUThread([slot = GetCurrentSlot()]() {
|
||||
VMManager::LoadStateFromSlot(slot, true);
|
||||
Error error;
|
||||
if (!VMManager::LoadStateFromSlot(slot, true, &error))
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
error.GetDescription(), Host::OSD_INFO_DURATION);
|
||||
});
|
||||
Close();
|
||||
}
|
||||
@@ -1374,6 +1423,7 @@ void ImGuiManager::RenderOverlays()
|
||||
|
||||
DrawVideoCaptureOverlay(position_y, scale, margin, spacing);
|
||||
DrawInputRecordingOverlay(position_y, scale, margin, spacing);
|
||||
DrawTextureReplacementsOverlay(position_y, scale, margin, spacing);
|
||||
if (GSConfig.OsdPerformancePos != OsdOverlayPos::None)
|
||||
DrawPerformanceOverlay(position_y, scale, margin, spacing);
|
||||
DrawSettingsOverlay(scale, margin, spacing);
|
||||
|
||||
@@ -870,10 +870,10 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
|
||||
key.data = 0;
|
||||
return key;
|
||||
}
|
||||
else if (binding[0] == '+' || binding[0] == '-')
|
||||
else if (binding[0] == '+' || binding[0] == '-' || binding.starts_with("Full"))
|
||||
{
|
||||
// likely an axis
|
||||
const std::string_view axis_name(binding.substr(1));
|
||||
const std::string_view axis_name(binding.substr(binding[0] == 'F' ? 4 : 1));
|
||||
|
||||
if (axis_name.starts_with("JoyAxis"))
|
||||
{
|
||||
@@ -882,7 +882,9 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
|
||||
{
|
||||
key.source_subtype = InputSubclass::ControllerAxis;
|
||||
key.data = *value + std::size(s_sdl_axis_setting_names);
|
||||
key.modifier = (binding[0] == '-') ? InputModifier::Negate : InputModifier::None;
|
||||
key.modifier = (binding[0] == 'F') ? InputModifier::FullAxis :
|
||||
(binding[0] == '-') ? InputModifier::Negate :
|
||||
InputModifier::None;
|
||||
key.invert = (end == "~");
|
||||
return key;
|
||||
}
|
||||
@@ -894,23 +896,13 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
|
||||
// found an axis!
|
||||
key.source_subtype = InputSubclass::ControllerAxis;
|
||||
key.data = i;
|
||||
key.modifier = (binding[0] == '-') ? InputModifier::Negate : InputModifier::None;
|
||||
key.modifier = (binding[0] == 'F') ? InputModifier::FullAxis :
|
||||
(binding[0] == '-') ? InputModifier::Negate :
|
||||
InputModifier::None;
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (binding.starts_with("FullJoyAxis"))
|
||||
{
|
||||
std::string_view end;
|
||||
if (auto value = StringUtil::FromChars<u32>(binding.substr(11), 10, &end))
|
||||
{
|
||||
key.source_subtype = InputSubclass::ControllerAxis;
|
||||
key.data = *value + std::size(s_sdl_axis_setting_names);
|
||||
key.modifier = InputModifier::FullAxis;
|
||||
key.invert = (end == "~");
|
||||
return key;
|
||||
}
|
||||
}
|
||||
else if (binding.starts_with("Hat"))
|
||||
{
|
||||
std::string_view hat_dir;
|
||||
|
||||
@@ -44,39 +44,39 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int mode;
|
||||
unsigned int attr;
|
||||
unsigned int size;
|
||||
unsigned char ctime[8];
|
||||
unsigned char atime[8];
|
||||
unsigned char mtime[8];
|
||||
unsigned int hisize;
|
||||
u32 mode;
|
||||
u32 attr;
|
||||
u32 size;
|
||||
u8 ctime[8];
|
||||
u8 atime[8];
|
||||
u8 mtime[8];
|
||||
u32 hisize;
|
||||
} fio_stat_t;
|
||||
typedef struct
|
||||
{
|
||||
fio_stat_t _fioStat;
|
||||
/** Number of subs (main) / subpart number (sub) */
|
||||
unsigned int private_0;
|
||||
unsigned int private_1;
|
||||
unsigned int private_2;
|
||||
unsigned int private_3;
|
||||
unsigned int private_4;
|
||||
u32 private_0;
|
||||
u32 private_1;
|
||||
u32 private_2;
|
||||
u32 private_3;
|
||||
u32 private_4;
|
||||
/** Sector start. */
|
||||
unsigned int private_5;
|
||||
u32 private_5;
|
||||
} fxio_stat_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fio_stat_t stat;
|
||||
char name[256];
|
||||
unsigned int unknown;
|
||||
u32 unknown;
|
||||
} fio_dirent_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fxio_stat_t stat;
|
||||
char name[256];
|
||||
unsigned int unknown;
|
||||
u32 unknown;
|
||||
} fxio_dirent_t;
|
||||
|
||||
static std::string hostRoot;
|
||||
@@ -171,7 +171,7 @@ namespace R3000A
|
||||
if (!FileSystem::StatFile(file_path.c_str(), &file_stats))
|
||||
return -IOP_ENOENT;
|
||||
|
||||
host_stats->size = file_stats.st_size;
|
||||
host_stats->size = (u32)file_stats.st_size;
|
||||
host_stats->hisize = 0;
|
||||
|
||||
// Convert the mode.
|
||||
@@ -315,13 +315,13 @@ namespace R3000A
|
||||
switch (whence)
|
||||
{
|
||||
case IOP_SEEK_SET:
|
||||
err = ::lseek(fd, offset, SEEK_SET);
|
||||
err = static_cast<int>(::lseek(fd, offset, SEEK_SET));
|
||||
break;
|
||||
case IOP_SEEK_CUR:
|
||||
err = ::lseek(fd, offset, SEEK_CUR);
|
||||
err = static_cast<int>(::lseek(fd, offset, SEEK_CUR));
|
||||
break;
|
||||
case IOP_SEEK_END:
|
||||
err = ::lseek(fd, offset, SEEK_END);
|
||||
err = static_cast<int>(::lseek(fd, offset, SEEK_END));
|
||||
break;
|
||||
default:
|
||||
return -IOP_EIO;
|
||||
@@ -332,12 +332,12 @@ namespace R3000A
|
||||
|
||||
virtual int read(void* buf, u32 count) /* Flawfinder: ignore */
|
||||
{
|
||||
return translate_error(::read(fd, buf, count));
|
||||
return translate_error(static_cast<int>(::read(fd, buf, count)));
|
||||
}
|
||||
|
||||
virtual int write(void* buf, u32 count)
|
||||
{
|
||||
return translate_error(::write(fd, buf, count));
|
||||
return translate_error(static_cast<int>(::write(fd, buf, count)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -762,7 +762,7 @@ namespace R3000A
|
||||
v0 = host_stat(full_path, (fxio_stat_t*)&buf);
|
||||
|
||||
for (size_t i = 0; i < sizeof(fxio_stat_t); i++)
|
||||
iopMemWrite8(data + i, buf[i]);
|
||||
iopMemWrite8(static_cast<u32>(data + i), buf[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -770,7 +770,7 @@ namespace R3000A
|
||||
v0 = host_stat(full_path, (fio_stat_t*)&buf);
|
||||
|
||||
for (size_t i = 0; i < sizeof(fio_stat_t); i++)
|
||||
iopMemWrite8(data + i, buf[i]);
|
||||
iopMemWrite8(static_cast<u32>(data + i), buf[i]);
|
||||
}
|
||||
pc = ra;
|
||||
return 1;
|
||||
|
||||
@@ -29,25 +29,6 @@ static void psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore)
|
||||
|
||||
const int size = (bcr >> 16) * (bcr & 0xFFFF);
|
||||
|
||||
// Update the spu2 to the current cycle before initiating the DMA
|
||||
|
||||
SPU2async();
|
||||
//Console.Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].startCycle);
|
||||
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = size * 4;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
|
||||
if ((psxRegs.iopNextEventCycle - psxNextStartCounter) > (u32)psxNextDeltaCounter)
|
||||
{
|
||||
//DevCon.Warning("SPU2async Setting new counter branch, old %x new %x ((%x - %x = %x) > %x delta)", g_iopNextEventCycle, psxNextStartCounter + psxNextCounter, g_iopNextEventCycle, psxNextStartCounter, (g_iopNextEventCycle - psxNextStartCounter), psxNextCounter);
|
||||
psxRegs.iopNextEventCycle = psxNextStartCounter + psxNextDeltaCounter;
|
||||
}
|
||||
|
||||
switch (chcr)
|
||||
{
|
||||
case 0x01000201: //cpu to spu2 transfer
|
||||
|
||||
@@ -186,7 +186,7 @@ void VU_Thread::ExecuteRingBuffer()
|
||||
break;
|
||||
case MTVU_VIF_UNPACK:
|
||||
{
|
||||
u32 vif_copy_size = (uptr)&vif.StructEnd - (uptr)&vif.tag;
|
||||
u32 vif_copy_size = static_cast<u32>((uptr)&vif.StructEnd - (uptr)&vif.tag);
|
||||
Read(&vif.tag, vif_copy_size);
|
||||
ReadRegs(&vifRegs);
|
||||
u32 size = Read();
|
||||
@@ -467,7 +467,7 @@ void VU_Thread::ExecuteVU(u32 vu_addr, u32 vif_top, u32 vif_itop, u32 fbrst)
|
||||
void VU_Thread::VifUnpack(vifStruct& _vif, VIFregisters& _vifRegs, const u8* data, u32 size)
|
||||
{
|
||||
MTVU_LOG("MTVU - VifUnpack!");
|
||||
u32 vif_copy_size = (uptr)&_vif.StructEnd - (uptr)&_vif.tag;
|
||||
u32 vif_copy_size = (u32)((uptr)&_vif.StructEnd - (uptr)&_vif.tag);
|
||||
ReserveSpace(1 + size_u32(vif_copy_size) + size_u32(sizeof(VIFregistersMTVU)) + 1 + size_u32(size));
|
||||
Write(MTVU_VIF_UNPACK);
|
||||
Write(&_vif.tag, vif_copy_size);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Elfheader.h"
|
||||
#include "PINE.h"
|
||||
#include "VMManager.h"
|
||||
#include "common/Error.h"
|
||||
#include "common/Threading.h"
|
||||
|
||||
#include <atomic>
|
||||
@@ -18,6 +19,7 @@
|
||||
#include <thread>
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "IconsFontAwesome6.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define read_portable(a, b, c) (recv(a, (char*)b, c, 0))
|
||||
@@ -654,7 +656,12 @@ PINEServer::IPCBuffer PINEServer::ParseCommand(std::span<u8> buf, std::vector<u8
|
||||
goto error;
|
||||
if (!SafetyChecks(buf_cnt, 1, ret_cnt, 0, buf_size)) [[unlikely]]
|
||||
goto error;
|
||||
Host::RunOnCPUThread([slot = FromSpan<u8>(buf, buf_cnt)] { VMManager::LoadStateFromSlot(slot); });
|
||||
Host::RunOnCPUThread([slot = FromSpan<u8>(buf, buf_cnt)] {
|
||||
Error state_error;
|
||||
if (!VMManager::LoadStateFromSlot(slot, false, &state_error))
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
state_error.GetDescription(), Host::OSD_INFO_DURATION);
|
||||
});
|
||||
buf_cnt += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -728,19 +728,20 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||
OsdShowSpeed = false;
|
||||
OsdShowFPS = false;
|
||||
OsdShowVPS = false;
|
||||
OsdShowCPU = false;
|
||||
OsdShowGPU = false;
|
||||
OsdShowResolution = false;
|
||||
OsdShowGSStats = false;
|
||||
OsdShowCPU = false;
|
||||
OsdShowGPU = false;
|
||||
OsdShowIndicators = true;
|
||||
OsdShowFrameTimes = false;
|
||||
OsdShowHardwareInfo = false;
|
||||
OsdShowVersion = false;
|
||||
OsdShowSettings = false;
|
||||
OsdshowPatches = false;
|
||||
OsdShowInputs = false;
|
||||
OsdShowFrameTimes = false;
|
||||
OsdShowVersion = false;
|
||||
OsdShowHardwareInfo = false;
|
||||
OsdShowVideoCapture = true;
|
||||
OsdShowInputRec = true;
|
||||
OsdShowTextureReplacements = true;
|
||||
|
||||
HWDownloadMode = GSHardwareDownloadMode::Enabled;
|
||||
HWSpinGPUForReadbacks = false;
|
||||
@@ -960,6 +961,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBool(OsdShowHardwareInfo);
|
||||
SettingsWrapBitBool(OsdShowVideoCapture);
|
||||
SettingsWrapBitBool(OsdShowInputRec);
|
||||
SettingsWrapBitBool(OsdShowTextureReplacements);
|
||||
|
||||
SettingsWrapBitBool(HWSpinGPUForReadbacks);
|
||||
SettingsWrapBitBool(HWSpinCPUForReadbacks);
|
||||
@@ -1844,6 +1846,7 @@ bool Pcsx2Config::PadOptions::Port::operator!=(const PadOptions::Port& right) co
|
||||
|
||||
Pcsx2Config::AchievementsOptions::AchievementsOptions()
|
||||
{
|
||||
bitset = 0;
|
||||
Enabled = false;
|
||||
HardcoreMode = false;
|
||||
EncoreMode = false;
|
||||
|
||||
@@ -66,12 +66,12 @@ const std::string& InputRecordingFile::getFilename() const noexcept
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
unsigned long InputRecordingFile::getTotalFrames() const noexcept
|
||||
u32 InputRecordingFile::getTotalFrames() const noexcept
|
||||
{
|
||||
return m_totalFrames;
|
||||
}
|
||||
|
||||
unsigned long InputRecordingFile::getUndoCount() const noexcept
|
||||
u32 InputRecordingFile::getUndoCount() const noexcept
|
||||
{
|
||||
return m_undoCount;
|
||||
}
|
||||
@@ -237,7 +237,7 @@ std::vector<PadData> InputRecordingFile::bulkReadPadData(u32 frameStart, u32 fra
|
||||
}
|
||||
|
||||
// TODO - no multi-tap support
|
||||
for (uint64_t currFrame = frameStart; currFrame < frameEnd; currFrame++)
|
||||
for (u32 currFrame = frameStart; currFrame < frameEnd; currFrame++)
|
||||
{
|
||||
const auto padData = readPadData(currFrame, port, 0);
|
||||
if (padData)
|
||||
|
||||
@@ -68,8 +68,8 @@ public:
|
||||
|
||||
// Retrieve the input recording's filename (not the path)
|
||||
const std::string& getFilename() const noexcept;
|
||||
unsigned long getTotalFrames() const noexcept;
|
||||
unsigned long getUndoCount() const noexcept;
|
||||
u32 getTotalFrames() const noexcept;
|
||||
u32 getUndoCount() const noexcept;
|
||||
|
||||
void logRecordingMetadata();
|
||||
std::vector<PadData> bulkReadPadData(u32 frameStart, u32 frameEnd, const uint port);
|
||||
@@ -92,8 +92,8 @@ private:
|
||||
bool m_savestate = false;
|
||||
|
||||
// An signed 32-bit frame limit is equivalent to 1.13 years of continuous 60fps footage
|
||||
unsigned long m_totalFrames = 0;
|
||||
unsigned long m_undoCount = 0;
|
||||
u32 m_totalFrames = 0;
|
||||
u32 m_undoCount = 0;
|
||||
|
||||
// Calculates the position of the current frame in the input recording
|
||||
size_t getRecordingBlockSeekPoint(const u32 frame) const noexcept;
|
||||
|
||||
@@ -345,16 +345,7 @@ void V_Core::FinishDMAwrite()
|
||||
|
||||
DMAICounter = (DMAICounter - ReadSize) * 4;
|
||||
|
||||
if (((psxCounters[6].startCycle + psxCounters[6].deltaCycles) - psxRegs.cycle) > (u32)DMAICounter)
|
||||
{
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = DMAICounter;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
}
|
||||
CounterUpdate(DMAICounter);
|
||||
|
||||
ActiveTSA = TDA;
|
||||
ActiveTSA &= 0xfffff;
|
||||
@@ -439,16 +430,7 @@ void V_Core::FinishDMAread()
|
||||
else
|
||||
DMAICounter = 4;
|
||||
|
||||
if (((psxCounters[6].startCycle + psxCounters[6].deltaCycles) - psxRegs.cycle) > (u32)DMAICounter)
|
||||
{
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = DMAICounter;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
}
|
||||
CounterUpdate(DMAICounter);
|
||||
|
||||
ActiveTSA = TDA;
|
||||
ActiveTSA &= 0xfffff;
|
||||
@@ -470,16 +452,7 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
|
||||
//Regs.ATTR |= 0x30;
|
||||
TADR = MADR + (size << 1);
|
||||
|
||||
if (((psxCounters[6].startCycle + psxCounters[6].deltaCycles) - psxRegs.cycle) > (u32)DMAICounter)
|
||||
{
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = DMAICounter;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
}
|
||||
CounterUpdate(DMAICounter);
|
||||
|
||||
if (SPU2::MsgDMA())
|
||||
{
|
||||
|
||||
@@ -80,6 +80,7 @@ void SPU2writeDMA7Mem(u16* pMem, u32 size);
|
||||
|
||||
extern u32 lClocks;
|
||||
|
||||
extern void CounterUpdate(u32 DMAICounter);
|
||||
extern void TimeUpdate(u32 cClocks);
|
||||
extern void SPU2_FastWrite(u32 rmem, u16 value);
|
||||
|
||||
|
||||
@@ -237,6 +237,84 @@ void V_Voice::Stop()
|
||||
ADSR.Phase = V_ADSR::PHASE_STOPPED;
|
||||
}
|
||||
|
||||
__forceinline void CounterUpdate(u32 DMAICounter)
|
||||
{
|
||||
if (((psxCounters[6].startCycle + psxCounters[6].deltaCycles) - psxRegs.cycle) > (u32)DMAICounter)
|
||||
{
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = DMAICounter;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void CheckDMAProgress(int cid)
|
||||
{
|
||||
V_Core& core = Cores[cid];
|
||||
int adma_cbit = 1 << cid;
|
||||
|
||||
if (core.DMAICounter > 0 && (psxRegs.cycle - core.LastClock) > 0)
|
||||
{
|
||||
const u32 amt = std::min(psxRegs.cycle - core.LastClock, (u32)core.DMAICounter);
|
||||
core.DMAICounter -= amt;
|
||||
core.LastClock = psxRegs.cycle;
|
||||
|
||||
if (!core.AdmaInProgress)
|
||||
{
|
||||
if (cid == 0)
|
||||
HW_DMA4_MADR += amt / 2;
|
||||
if (cid == 1)
|
||||
HW_DMA7_MADR += amt / 2;
|
||||
}
|
||||
|
||||
if (core.DMAICounter > 0)
|
||||
{
|
||||
CounterUpdate(core.DMAICounter);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (has_to_call_irq_dma[i])
|
||||
{
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq_dma[i] = false;
|
||||
if (!(Spdif.Info & (4 << i)) && Cores[i].IRQEnable)
|
||||
{
|
||||
Spdif.Info |= (4 << i);
|
||||
spu2Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((core.AutoDMACtrl & adma_cbit) != adma_cbit) && core.ReadSize)
|
||||
{
|
||||
if (core.IsDMARead)
|
||||
core.FinishDMAread();
|
||||
else
|
||||
core.FinishDMAwrite();
|
||||
}
|
||||
|
||||
if (core.DMAICounter <= 0)
|
||||
{
|
||||
if (cid == 0)
|
||||
{
|
||||
HW_DMA4_MADR = HW_DMA4_TADR;
|
||||
spu2DMA4Irq();
|
||||
}
|
||||
|
||||
if (cid == 1)
|
||||
{
|
||||
HW_DMA7_MADR = HW_DMA7_TADR;
|
||||
spu2DMA7Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint TickInterval = 768;
|
||||
static constexpr int SanityInterval = 4800;
|
||||
|
||||
@@ -302,112 +380,8 @@ __forceinline void TimeUpdate(u32 cClocks)
|
||||
spu2Mix();
|
||||
}
|
||||
|
||||
//Update DMA4 interrupt delay counter
|
||||
if (Cores[0].DMAICounter > 0 && (psxRegs.cycle - Cores[0].LastClock) > 0)
|
||||
{
|
||||
const u32 amt = std::min(psxRegs.cycle - Cores[0].LastClock, (u32)Cores[0].DMAICounter);
|
||||
Cores[0].DMAICounter -= amt;
|
||||
Cores[0].LastClock = psxRegs.cycle;
|
||||
if(!Cores[0].AdmaInProgress)
|
||||
HW_DMA4_MADR += amt / 2;
|
||||
|
||||
if (Cores[0].DMAICounter <= 0)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (has_to_call_irq_dma[i])
|
||||
{
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq_dma[i] = false;
|
||||
if (!(Spdif.Info & (4 << i)) && Cores[i].IRQEnable)
|
||||
{
|
||||
Spdif.Info |= (4 << i);
|
||||
spu2Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((Cores[0].AutoDMACtrl & 1) != 1) && Cores[0].ReadSize)
|
||||
{
|
||||
if (Cores[0].IsDMARead)
|
||||
Cores[0].FinishDMAread();
|
||||
else
|
||||
Cores[0].FinishDMAwrite();
|
||||
}
|
||||
|
||||
if (Cores[0].DMAICounter <= 0)
|
||||
{
|
||||
HW_DMA4_MADR = HW_DMA4_TADR;
|
||||
spu2DMA4Irq();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((psxCounters[6].startCycle + psxCounters[6].deltaCycles) - psxRegs.cycle) > (u32)Cores[0].DMAICounter)
|
||||
{
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = Cores[0].DMAICounter;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Update DMA7 interrupt delay counter
|
||||
if (Cores[1].DMAICounter > 0 && (psxRegs.cycle - Cores[1].LastClock) > 0)
|
||||
{
|
||||
const u32 amt = std::min(psxRegs.cycle - Cores[1].LastClock, (u32)Cores[1].DMAICounter);
|
||||
Cores[1].DMAICounter -= amt;
|
||||
Cores[1].LastClock = psxRegs.cycle;
|
||||
if (!Cores[1].AdmaInProgress)
|
||||
HW_DMA7_MADR += amt / 2;
|
||||
if (Cores[1].DMAICounter <= 0)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (has_to_call_irq_dma[i])
|
||||
{
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq_dma[i] = false;
|
||||
if (!(Spdif.Info & (4 << i)) && Cores[i].IRQEnable)
|
||||
{
|
||||
Spdif.Info |= (4 << i);
|
||||
spu2Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((Cores[1].AutoDMACtrl & 2) != 2) && Cores[1].ReadSize)
|
||||
{
|
||||
if (Cores[1].IsDMARead)
|
||||
Cores[1].FinishDMAread();
|
||||
else
|
||||
Cores[1].FinishDMAwrite();
|
||||
}
|
||||
|
||||
if (Cores[1].DMAICounter <= 0)
|
||||
{
|
||||
HW_DMA7_MADR = HW_DMA7_TADR;
|
||||
spu2DMA7Irq();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((psxCounters[6].startCycle + psxCounters[6].deltaCycles) - psxRegs.cycle) > (u32)Cores[1].DMAICounter)
|
||||
{
|
||||
psxCounters[6].startCycle = psxRegs.cycle;
|
||||
psxCounters[6].deltaCycles = Cores[1].DMAICounter;
|
||||
|
||||
psxNextDeltaCounter -= (psxRegs.cycle - psxNextStartCounter);
|
||||
psxNextStartCounter = psxRegs.cycle;
|
||||
if (psxCounters[6].deltaCycles < psxNextDeltaCounter)
|
||||
psxNextDeltaCounter = psxCounters[6].deltaCycles;
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckDMAProgress(0);
|
||||
CheckDMAProgress(1);
|
||||
}
|
||||
|
||||
__forceinline void UpdateSpdifMode()
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace VMManager
|
||||
static void PrecacheCDVDFile();
|
||||
|
||||
static std::string GetCurrentSaveStateFileName(s32 slot, bool backup = false);
|
||||
static bool DoLoadState(const char* filename);
|
||||
static bool DoLoadState(const char* filename, Error* error = nullptr);
|
||||
static bool DoSaveState(const char* filename, s32 slot_for_message, bool zip_on_thread, bool backup_old_state);
|
||||
static void ZipSaveState(std::unique_ptr<ArchiveEntryList> elist,
|
||||
std::unique_ptr<SaveStateScreenshotData> screenshot, std::string osd_key, const char* filename,
|
||||
@@ -1589,8 +1589,10 @@ bool VMManager::Initialize(VMBootParameters boot_params)
|
||||
// do we want to load state?
|
||||
if (!GSDumpReplayer::IsReplayingDump() && !state_to_load.empty())
|
||||
{
|
||||
if (!DoLoadState(state_to_load.c_str()))
|
||||
Error state_error;
|
||||
if (!DoLoadState(state_to_load.c_str(), &state_error))
|
||||
{
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("VMManager", "Failed to load save state."), state_error.GetDescription());
|
||||
Shutdown(false);
|
||||
return false;
|
||||
}
|
||||
@@ -1824,19 +1826,18 @@ std::string VMManager::GetCurrentSaveStateFileName(s32 slot, bool backup)
|
||||
return GetSaveStateFileName(s_disc_serial.c_str(), s_disc_crc, slot, backup);
|
||||
}
|
||||
|
||||
bool VMManager::DoLoadState(const char* filename)
|
||||
bool VMManager::DoLoadState(const char* filename, Error* error)
|
||||
{
|
||||
if (GSDumpReplayer::IsReplayingDump())
|
||||
{
|
||||
Error::SetString(error, TRANSLATE_STR("VMManager", "Cannot load save state while replaying GS dump."));
|
||||
return false;
|
||||
}
|
||||
|
||||
Host::OnSaveStateLoading(filename);
|
||||
|
||||
Error error;
|
||||
if (!SaveState_UnzipFromDisk(filename, &error))
|
||||
{
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("VMManager", "Failed to load save state"), error.GetDescription());
|
||||
if (!SaveState_UnzipFromDisk(filename, error))
|
||||
return false;
|
||||
}
|
||||
|
||||
Host::OnSaveStateLoaded(filename, true);
|
||||
if (g_InputRecording.isActive())
|
||||
@@ -1980,62 +1981,70 @@ u32 VMManager::DeleteSaveStates(const char* game_serial, u32 game_crc, bool also
|
||||
return deleted;
|
||||
}
|
||||
|
||||
bool VMManager::LoadState(const char* filename)
|
||||
bool VMManager::LoadState(const char* filename, Error* error)
|
||||
{
|
||||
if (Achievements::IsHardcoreModeActive())
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadStateHardcoreBlocked", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
TRANSLATE_SV("VMManager", "Cannot load save state while RetroAchievements Hardcore Mode is active."),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
Error::SetString(error,
|
||||
TRANSLATE_STR("VMManager", "Cannot load save state while RetroAchievements Hardcore Mode is active."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MemcardBusy::IsBusy())
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("VMManager", "Failed to load state (Memory card is busy)")),
|
||||
Host::OSD_QUICK_DURATION);
|
||||
Error::SetString(error,
|
||||
TRANSLATE_STR("VMManager", "Memory card is busy."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Save the current state so we don't need to reset.
|
||||
if (DoLoadState(filename))
|
||||
if (DoLoadState(filename, error))
|
||||
return true;
|
||||
|
||||
Reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VMManager::LoadStateFromSlot(s32 slot, bool backup)
|
||||
bool VMManager::LoadStateFromSlot(s32 slot, bool backup, Error* error)
|
||||
{
|
||||
const std::string filename = GetCurrentSaveStateFileName(slot, backup);
|
||||
if (filename.empty() || !FileSystem::FileExists(filename.c_str()))
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("VMManager", "There is no saved {} in slot {}."), backup ? TRANSLATE("VMManager", "backup state") : "state", slot),
|
||||
Host::OSD_QUICK_DURATION);
|
||||
if (backup)
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("VMManager", "There is no save state in backup slot {}."), slot);
|
||||
else
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("VMManager", "There is no save state in slot {}."), slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Achievements::IsHardcoreModeActive())
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadStateHardcoreBlocked", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("VMManager", "Cannot load save {} from slot {} while RetroAchievements Hardcore Mode is active."), backup ? TRANSLATE("VMManager", "backup state") : TRANSLATE("VMManager", "state"), slot),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
if (backup)
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("VMManager", "Cannot load save state from backup slot {} while RetroAchievements Hardcore Mode is active."), slot);
|
||||
else
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("VMManager", "Cannot load save state from slot {} while RetroAchievements Hardcore Mode is active."), slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (MemcardBusy::IsBusy())
|
||||
{
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_TRIANGLE_EXCLAMATION,
|
||||
fmt::format(TRANSLATE_FS("VMManager", "Failed to load {} from slot {} (Memory card is busy)"), backup ? TRANSLATE("VMManager", "backup state") : TRANSLATE("VMManager", "state"), slot),
|
||||
Host::OSD_QUICK_DURATION);
|
||||
if (backup)
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("VMManager", "Failed to load save state from backup slot {} (memory card is busy)."), slot);
|
||||
else
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("VMManager", "Failed to load save state from slot {} (memory card is busy)."), slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_FOLDER_OPEN,
|
||||
fmt::format(TRANSLATE_FS("VMManager", "Loading {} from slot {}..."), backup ? TRANSLATE("VMManager", "backup state") : TRANSLATE("VMManager", "state"), slot), Host::OSD_QUICK_DURATION);
|
||||
return DoLoadState(filename.c_str());
|
||||
|
||||
return DoLoadState(filename.c_str(), error);
|
||||
}
|
||||
|
||||
bool VMManager::SaveState(const char* filename, bool zip_on_thread, bool backup_old_state)
|
||||
|
||||