mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9955e07470 | ||
|
|
74db386144 | ||
|
|
3f72efeb7a | ||
|
|
d0f8905439 | ||
|
|
5a60259ef5 | ||
|
|
c8dffccaa7 | ||
|
|
87a82b16ff | ||
|
|
5666902638 | ||
|
|
f1dc232f91 | ||
|
|
5476c5a17f | ||
|
|
9aabb197e6 | ||
|
|
c2488c9269 | ||
|
|
7e40ab8e7e | ||
|
|
902b3c5033 | ||
|
|
4d1afb9fdd | ||
|
|
4209900351 | ||
|
|
780c599b49 | ||
|
|
908d35bf77 | ||
|
|
cfea84b934 | ||
|
|
e5d94e255b | ||
|
|
080858b97c | ||
|
|
d883076573 | ||
|
|
b80101fbd6 | ||
|
|
aca775f8b8 | ||
|
|
4f4a26769c | ||
|
|
d19eaa1b8e | ||
|
|
be1af0cd0f | ||
|
|
6ab02e76f1 | ||
|
|
f87bc7d72b | ||
|
|
086f4f11e1 | ||
|
|
6f54da6234 | ||
|
|
44f47f11b8 | ||
|
|
b5a2d04b2e | ||
|
|
8508ebb7d3 | ||
|
|
3234e45f33 | ||
|
|
53d1320d83 | ||
|
|
9b545809be | ||
|
|
79400acf2a | ||
|
|
3107c4103a | ||
|
|
68c88f692e | ||
|
|
df19b37d6d | ||
|
|
1b5c352566 | ||
|
|
bed6a9e4d4 | ||
|
|
d602ad1d3e | ||
|
|
51c31347df | ||
|
|
00876e7076 | ||
|
|
47eb499893 | ||
|
|
b8680c3139 | ||
|
|
9b4e3b8f74 | ||
|
|
3e858167bc | ||
|
|
44d66555cc | ||
|
|
c5438ceca3 | ||
|
|
3e1927ae44 | ||
|
|
b688117002 | ||
|
|
e62e6fb6c3 | ||
|
|
262e94e5d7 | ||
|
|
11a4b4e7ff | ||
|
|
a98cfcf28c | ||
|
|
d02f30ee62 | ||
|
|
c0bf01a646 | ||
|
|
babb985e9e | ||
|
|
e379c8317d | ||
|
|
5098277474 | ||
|
|
4a94cb6cbd | ||
|
|
e245454b91 | ||
|
|
b003eadd2d | ||
|
|
a5984d8213 | ||
|
|
4dbd95b0bb | ||
|
|
68803229da | ||
|
|
b661a2a149 | ||
|
|
63cd355d7a | ||
|
|
0f5ff68679 | ||
|
|
bd74921926 | ||
|
|
78f83514f4 | ||
|
|
2c36259b88 | ||
|
|
32a0bed6af | ||
|
|
d415f8364c | ||
|
|
7c768b6833 | ||
|
|
773f6968a4 | ||
|
|
1021199512 | ||
|
|
08ef9e2bd9 | ||
|
|
6ba3f96f27 | ||
|
|
7d5b7bc3ce | ||
|
|
0d43d30346 | ||
|
|
da824b4e9e | ||
|
|
ed08b5f34e | ||
|
|
0ce312c1c3 | ||
|
|
07bc2fa452 | ||
|
|
bfd2775074 | ||
|
|
94ccafd745 | ||
|
|
5c6049c4ae | ||
|
|
090464c42d | ||
|
|
89a00db3d6 | ||
|
|
fc415dff93 | ||
|
|
f648a9a438 | ||
|
|
cac6669423 | ||
|
|
7db487a49b | ||
|
|
c96607fe37 | ||
|
|
ba0dae5f57 | ||
|
|
5fe5148e86 | ||
|
|
5445cb516a | ||
|
|
84a29ffcca | ||
|
|
e56075976f | ||
|
|
0f709735c0 | ||
|
|
ad3f0fd6cd | ||
|
|
fbfdacd589 | ||
|
|
aedc51e151 | ||
|
|
fe95a697f4 | ||
|
|
f99cf28429 | ||
|
|
bea1eb0cf9 | ||
|
|
3cf21e0ab6 | ||
|
|
521b32c253 | ||
|
|
190b525ca6 | ||
|
|
baa00e4d38 | ||
|
|
51bc6c1465 | ||
|
|
ea8492082a | ||
|
|
9d1fd23d78 | ||
|
|
9ff575377d | ||
|
|
47250293cd | ||
|
|
f9b346521d | ||
|
|
b5a4c71eff | ||
|
|
2604256424 | ||
|
|
906ac6a8ea | ||
|
|
3db21e0579 | ||
|
|
abd03884de | ||
|
|
a159256b07 |
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1,3 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [PCSX2]
|
||||
liberapay: PCSX2
|
||||
|
||||
7
.github/labeler.yml
vendored
7
.github/labeler.yml
vendored
@@ -40,6 +40,13 @@
|
||||
- 'pcsx2-qt/**/*'
|
||||
- '3rdparty/Qt/*'
|
||||
- '3rdparty/Qt/**/*'
|
||||
'OSD / ImGui':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'pcsx2/ImGui/*'
|
||||
- 'pcsx2/ImGui/**/*'
|
||||
- '3rdparty/imgui/*'
|
||||
- '3rdparty/imgui/**/*'
|
||||
'GameDB':
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
||||
8
.github/workflows/linux_build_flatpak.yml
vendored
8
.github/workflows/linux_build_flatpak.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.7
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.9
|
||||
options: --privileged
|
||||
timeout-minutes: 60
|
||||
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (beta)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@92ae9851ad316786193b1fd3f40c4b51eb5cb101
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
@@ -138,7 +138,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (stable)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@92ae9851ad316786193b1fd3f40c4b51eb5cb101
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
mv "./${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak" "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
|
||||
4
.github/workflows/linux_build_qt.yml
vendored
4
.github/workflows/linux_build_qt.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 500M
|
||||
CCACHE_MAXSIZE: 100M
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
@@ -174,7 +174,7 @@ jobs:
|
||||
|
||||
- name: Upload artifact
|
||||
if: inputs.buildAppImage == true
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
|
||||
13
.github/workflows/macos_build.yml
vendored
13
.github/workflows/macos_build.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: macos-15
|
||||
default: macos-26
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 500M
|
||||
CCACHE_MAXSIZE: 100M
|
||||
# Only way to use a secret in an if statement
|
||||
SIGN_KEY: ${{ secrets.APPLE_SIGN_P12_B64 }}
|
||||
|
||||
@@ -62,8 +62,11 @@ jobs:
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Use Xcode 16.4
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.4.app
|
||||
- name: Use Xcode 26.0.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
|
||||
|
||||
- name: Install Metal Toolchain
|
||||
run: xcodebuild -downloadComponent MetalToolchain
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
@@ -194,7 +197,7 @@ jobs:
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS.tar.xz
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: "*.tar.xz"
|
||||
|
||||
8
.github/workflows/release_cut_new.yml
vendored
8
.github/workflows/release_cut_new.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release (Manual)
|
||||
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
|
||||
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090
|
||||
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
name: Download all Artifacts
|
||||
with:
|
||||
path: ./ci-artifacts/
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
|
||||
- uses: actions/setup-node@v5
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.24
|
||||
SDL=SDL3-3.2.26
|
||||
QT=6.10.0
|
||||
QTAPNG=1.3.0
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
KDDOCKWIDGETS=2.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
@@ -44,7 +44,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
81cc0fc17e5bf2c1754eeca9af9c47a76789ac5efdd165b3b91cbbe4b90bfb76 $SDL.tar.gz
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
@@ -59,7 +59,7 @@ a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADE
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
843baf9e1812c1ab82fd81d85b57cbc0d29bb43245efeb2539039780004b1056 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
@@ -116,7 +116,9 @@ echo "Building libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build -G Ninja
|
||||
# On non debian or debian based Linux systems, libjpeg-turbo will set CMAKE_INSTALL_DEFAULT_LIBDIR "lib64" (or libx32)
|
||||
# That will prevent CMake from finding the deps libjpeg later on. if we set CMAKE_INSTALL_DEFAULT_LIBDIR, libjpeg-turbo will leave it as is, so set it to "lib"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -DCMAKE_INSTALL_DEFAULT_LIBDIR="lib" -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.24.tar.gz",
|
||||
"sha256": "81cc0fc17e5bf2c1754eeca9af9c47a76789ac5efdd165b3b91cbbe4b90bfb76"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.26.tar.gz",
|
||||
"sha256": "dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"app-id": "net.pcsx2.PCSX2",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.9",
|
||||
"runtime-version": "6.10",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.llvm18"
|
||||
"org.freedesktop.Sdk.Extension.llvm20"
|
||||
],
|
||||
"add-extensions": {
|
||||
"org.freedesktop.Platform.ffmpeg-full": {
|
||||
"directory": "lib/ffmpeg",
|
||||
"version": "24.08",
|
||||
"version": "25.08",
|
||||
"add-ld-path": ".",
|
||||
"autodownload": true
|
||||
}
|
||||
@@ -50,8 +50,8 @@
|
||||
"-DCMAKE_PREFIX_PATH=\"${FLATPAK_DEST}\"",
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON",
|
||||
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm18/bin/clang",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm18/bin/clang++",
|
||||
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm20/bin/clang",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm20/bin/clang++",
|
||||
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DCMAKE_MODULE_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
"-DCMAKE_SHARED_LINKER_FLAGS_INIT=-fuse-ld=lld",
|
||||
|
||||
@@ -40,7 +40,7 @@ fi
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
SDL=SDL3-3.2.24
|
||||
SDL=SDL3-3.2.26
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
@@ -50,7 +50,7 @@ FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.10.0
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
@@ -80,7 +80,7 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
cat > SHASUMS <<EOF
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
81cc0fc17e5bf2c1754eeca9af9c47a76789ac5efdd165b3b91cbbe4b90bfb76 $SDL.tar.gz
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
@@ -99,7 +99,7 @@ a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADE
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
843baf9e1812c1ab82fd81d85b57cbc0d29bb43245efeb2539039780004b1056 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
@@ -22,7 +22,7 @@ fi
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
SDL=SDL3-3.2.24
|
||||
SDL=SDL3-3.2.26
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
@@ -32,7 +32,7 @@ FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.10.0
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
@@ -61,7 +61,7 @@ CMAKE_COMMON=(
|
||||
cat > SHASUMS <<EOF
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
81cc0fc17e5bf2c1754eeca9af9c47a76789ac5efdd165b3b91cbbe4b90bfb76 $SDL.tar.gz
|
||||
dad488474a51a0b01d547cd2834893d6299328d2e30f479a3564088b5476bae2 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
@@ -80,7 +80,7 @@ a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADE
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
843baf9e1812c1ab82fd81d85b57cbc0d29bb43245efeb2539039780004b1056 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
@@ -237,6 +237,9 @@ 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.
|
||||
|
||||
16
.github/workflows/scripts/macos/clickbutton.patch
vendored
Normal file
16
.github/workflows/scripts/macos/clickbutton.patch
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
--- 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
|
||||
@@ -47,7 +47,7 @@ set HARFBUZZ=12.0.0
|
||||
set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1650
|
||||
set LIBPNGLONG=1.6.50
|
||||
set SDL=SDL3-3.2.24
|
||||
set SDL=SDL3-3.2.26
|
||||
set QT=6.10.0
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
@@ -56,7 +56,7 @@ set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.3.0
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.1
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
@@ -71,8 +71,7 @@ call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lp
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 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" ca7fe2ca54a97e047f5eff236e62ae87546e862f509f0a62fc6e564ded3c6a95 || goto error
|
||||
call :downloadfile "SDL-7914bdb7ea14ee5109d50df857c8dfc69a28a62d.patch" https://github.com/libsdl-org/SDL/commit/7914bdb7ea14ee5109d50df857c8dfc69a28a62d.patch 5c09a29a9cac87a85ec3b8f5a68ff0e5c6c47229f3e2282241b9c32166f26977 || 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
|
||||
@@ -82,7 +81,7 @@ call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/arch
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" d2b9592ebe5d053ac97a0213ea35139866d8d5e0a1d84b7d3fb581db7f0b01c6 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 615184f756d91ce416f2cf883bb67fd4262651417c2e40c4d681c8641a48263e || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
|
||||
@@ -97,7 +96,7 @@ if %DEBUG%==1 (
|
||||
echo Building release libraries...
|
||||
)
|
||||
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG"
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_SHARED_LINKER_FLAGS_MINSIZEREL="/DEBUG"
|
||||
set ARM64TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE="%SCRIPTDIR%\cmake-toolchain-windows-arm64.cmake"
|
||||
|
||||
echo Building Zlib...
|
||||
@@ -189,7 +188,6 @@ echo Building SDL...
|
||||
rmdir /S /Q "%SDL%"
|
||||
%SEVENZIP% x "%SDL%.zip" || goto error
|
||||
cd "%SDL%" || goto error
|
||||
%PATCH% -p1 < "..\SDL-7914bdb7ea14ee5109d50df857c8dfc69a28a62d.patch" || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -199,7 +197,7 @@ cd .. || goto error
|
||||
if %DEBUG%==1 (
|
||||
set QTBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -G "Ninja Multi-Config"
|
||||
) else (
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=MinSizeRel -G Ninja
|
||||
)
|
||||
|
||||
echo Building Qt base...
|
||||
|
||||
@@ -44,7 +44,7 @@ set FREETYPE=2.14.1
|
||||
set HARFBUZZ=12.0.0
|
||||
set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.24
|
||||
set SDL=SDL3-3.2.26
|
||||
set LIBPNGLONG=1.6.50
|
||||
set QT=6.10.0
|
||||
set QTMINOR=6.10
|
||||
@@ -54,7 +54,7 @@ set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.3.0
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.1
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
@@ -69,8 +69,7 @@ call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lp
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 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" ca7fe2ca54a97e047f5eff236e62ae87546e862f509f0a62fc6e564ded3c6a95 || goto error
|
||||
call :downloadfile "SDL-7914bdb7ea14ee5109d50df857c8dfc69a28a62d.patch" https://github.com/libsdl-org/SDL/commit/7914bdb7ea14ee5109d50df857c8dfc69a28a62d.patch 5c09a29a9cac87a85ec3b8f5a68ff0e5c6c47229f3e2282241b9c32166f26977 || 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
|
||||
@@ -80,7 +79,7 @@ call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/arch
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" d2b9592ebe5d053ac97a0213ea35139866d8d5e0a1d84b7d3fb581db7f0b01c6 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 615184f756d91ce416f2cf883bb67fd4262651417c2e40c4d681c8641a48263e || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
|
||||
@@ -95,7 +94,7 @@ if %DEBUG%==1 (
|
||||
echo Building release libraries...
|
||||
)
|
||||
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_RELEASE="/DEBUG"
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_SHARED_LINKER_FLAGS_MINSIZEREL="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_MINSIZEREL="/DEBUG"
|
||||
|
||||
echo Building Zlib...
|
||||
rmdir /S /Q "zlib-%ZLIB%"
|
||||
@@ -186,7 +185,6 @@ echo Building SDL...
|
||||
rmdir /S /Q "%SDL%"
|
||||
%SEVENZIP% x "%SDL%.zip" || goto error
|
||||
cd "%SDL%" || goto error
|
||||
%PATCH% -p1 < "..\SDL-7914bdb7ea14ee5109d50df857c8dfc69a28a62d.patch" || goto error
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
@@ -196,7 +194,7 @@ cd .. || goto error
|
||||
if %DEBUG%==1 (
|
||||
set QTBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -G "Ninja Multi-Config"
|
||||
) else (
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
set QTBUILDSPEC=-DCMAKE_BUILD_TYPE=MinSizeRel -G Ninja
|
||||
)
|
||||
|
||||
echo Building Qt base...
|
||||
|
||||
4
.github/workflows/windows_build_qt.yml
vendored
4
.github/workflows/windows_build_qt.yml
vendored
@@ -154,7 +154,7 @@ jobs:
|
||||
cmake --build build --config Release --target unittests
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: |
|
||||
@@ -186,7 +186,7 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Upload artifact - with symbols
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}-symbols
|
||||
path: |
|
||||
|
||||
Binary file not shown.
@@ -1,58 +0,0 @@
|
||||
|
||||
†---------------------†
|
||||
|
||||
Disassembly view:
|
||||
|
||||
†---------------------†
|
||||
|
||||
Ctrl + G Goto
|
||||
Ctrl + E Edit Breakpoint
|
||||
Ctrl + D Enable/disable breakpoint
|
||||
Ctrl + B Add breakpoint
|
||||
Left Go back one branch level/goto pc
|
||||
Right Follow branch/position memory view to accessed address
|
||||
Up Move cursor up one line
|
||||
Down Move cursor down one line
|
||||
Page Up Move visible area up one page
|
||||
Page Down Move visible area down one page
|
||||
F10 Step over
|
||||
F11 Step into
|
||||
Tab Toggle display symbols
|
||||
Left Click Select line/toggle breakpoint if line is already highlighted
|
||||
Right Click Open context menu
|
||||
|
||||
†---------------------†
|
||||
|
||||
Memory View:
|
||||
|
||||
†---------------------†
|
||||
|
||||
Ctrl + G Goto
|
||||
Ctrl + B Add breakpoint
|
||||
Left Move cursor back one byte/nibble
|
||||
Right Move cursor ahead one byte/nibble
|
||||
Up Move cursor up one line
|
||||
Down Move cursor down one line
|
||||
Page Up Move cursor up one page
|
||||
Page Down Move cursor down one page
|
||||
0-9,A-F Overwrite hex nibble
|
||||
Any Overwrite ansi byte
|
||||
Left Click Select byte/nibble
|
||||
Right Click Open context menu
|
||||
Ctrl+Wheel Zoom memory view
|
||||
Esc Return to previous goto address
|
||||
Ctrl+V Paste a hex string into memory
|
||||
|
||||
†---------------------†
|
||||
|
||||
Breakpoint List:
|
||||
|
||||
†---------------------†
|
||||
|
||||
Up Select previous item
|
||||
Down Select next item
|
||||
Delete Remove selected breakpoint
|
||||
Return Edit selected breakpoint
|
||||
Space Toggle enable state of selected breakpoint
|
||||
|
||||
†---------------------†
|
||||
@@ -1840,6 +1840,8 @@ SCAJ-20095:
|
||||
region: "NTSC-Unk"
|
||||
gameFixes:
|
||||
- EETimingHack
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SCAJ-20096:
|
||||
name: "Guilty Gear Isuka"
|
||||
region: "NTSC-Unk"
|
||||
@@ -2063,10 +2065,13 @@ SCAJ-20129:
|
||||
name: "Ponkotsu Roman Daikatsugeki Bumpy Trot"
|
||||
region: "NTSC-Unk"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SCAJ-20130:
|
||||
name: "Namco x Capcom"
|
||||
region: "NTSC-Unk"
|
||||
@@ -2364,9 +2369,13 @@ SCAJ-20171:
|
||||
name-en: "Zettai Zetsumei Toshi 2 - Itetsuita Kioku Tachi"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_ZettaiZetsumeiToshi2"
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SCAJ-20172:
|
||||
name: "Final Fantasy XII"
|
||||
region: "NTSC-Unk"
|
||||
@@ -3821,9 +3830,13 @@ SCED-52491:
|
||||
SCED-52496:
|
||||
name: "This Is Football 2004 [Demo]"
|
||||
region: "PAL-M4"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCED-52497:
|
||||
name: "This Is Football 2004 [Demo]"
|
||||
region: "PAL-M4"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCED-52549:
|
||||
name: "Official PlayStation 2 Magazine Demo 47"
|
||||
region: "PAL-M5"
|
||||
@@ -5391,18 +5404,28 @@ SCES-51608:
|
||||
SCES-51610:
|
||||
name: "This is Football 2004 [Red Devils 2004]"
|
||||
region: "PAL-BE"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCES-51611:
|
||||
name: "This is Football 2004"
|
||||
region: "PAL-M4"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCES-51612:
|
||||
name: "This is Football 5"
|
||||
name: "This Is Football 2004"
|
||||
region: "PAL-E-N"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCES-51613:
|
||||
name: "This is Football 2004"
|
||||
region: "PAL-M4"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCES-51614:
|
||||
name: "Monde des Bleus 2004, Le - Nouvelle Generation"
|
||||
region: "PAL-F"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCES-51618:
|
||||
name: "SOCOM - U.S. Navy SEALs"
|
||||
region: "PAL-M5"
|
||||
@@ -7556,10 +7579,13 @@ SCKA-20058:
|
||||
name-en: "Action Romance Bumpy Trot"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SCKA-20059:
|
||||
name: "소울칼리버 Ⅲ"
|
||||
name-en: "SoulCalibur III"
|
||||
@@ -11011,7 +11037,7 @@ SCUS-97115:
|
||||
recommendedBlendingLevel: 3 # Improves banding in car showcase as well as car brightness and sheen.
|
||||
getSkipCount: "GSC_PolyphonyDigitalGames" # Fixes post-processing.
|
||||
SCUS-97116:
|
||||
name: "Kiosk Demo Disc 2.01"
|
||||
name: "Kiosk Disc 2.1"
|
||||
region: "NTSC-U"
|
||||
SCUS-97117:
|
||||
name: "PlayStation 2 Demo Disc Version 2.1 [Need for Speed - Underground]"
|
||||
@@ -11049,7 +11075,7 @@ SCUS-97126:
|
||||
name: "PlayStation 2 Demo Disc Version 2.2"
|
||||
region: "NTSC-U"
|
||||
SCUS-97127:
|
||||
name: "Kiosk Demo Disc 2.02"
|
||||
name: "Kiosk Disc 2.2"
|
||||
region: "NTSC-U"
|
||||
SCUS-97128:
|
||||
name: "Drakan - The Ancients' Gates"
|
||||
@@ -11120,7 +11146,7 @@ SCUS-97140:
|
||||
patch=0,EE,0032940C,word,48459000
|
||||
patch=0,EE,00329420,word,4BDAD1FF
|
||||
SCUS-97142:
|
||||
name: "Primal - Civilization Is Only Skin Deep"
|
||||
name: "Primal"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
roundModes:
|
||||
@@ -11166,7 +11192,7 @@ SCUS-97155:
|
||||
name: "PlayStation 2 Demo Disc Version 2.3"
|
||||
region: "NTSC-U"
|
||||
SCUS-97156:
|
||||
name: "Kiosk Demo Disc 2.03"
|
||||
name: "Kiosk Demo Disc 2.3"
|
||||
region: "NTSC-U"
|
||||
SCUS-97157:
|
||||
name: "Frequency [Demo]"
|
||||
@@ -11247,7 +11273,7 @@ SCUS-97173:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SCUS-97174:
|
||||
name: "Kiosk Demo Disc 2.04"
|
||||
name: "Kiosk Demo Disc 2.4"
|
||||
region: "NTSC-U"
|
||||
SCUS-97175:
|
||||
name: "NCAA Final Four 2002 [Demo]"
|
||||
@@ -11345,7 +11371,7 @@ SCUS-97199:
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 1 # Fixes light blooms.
|
||||
SCUS-97200:
|
||||
name: "Kiosk Demo Disc 2.05"
|
||||
name: "Kiosk Demo Disc 2.5"
|
||||
region: "NTSC-U"
|
||||
SCUS-97201:
|
||||
name: "The Mark of Kri"
|
||||
@@ -11425,7 +11451,7 @@ SCUS-97216:
|
||||
name: "PlayStation Underground Summer Sampler"
|
||||
region: "NTSC-U"
|
||||
SCUS-97217:
|
||||
name: "NBA Shootout 2003"
|
||||
name: "NBA ShootOut 2003"
|
||||
region: "NTSC-U"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes an issue with loading screens which cause the game to return on the Bios.
|
||||
@@ -11433,7 +11459,7 @@ SCUS-97217:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken player rendering and skin flashing.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
SCUS-97218:
|
||||
name: "Kiosk Demo Disc 2.06"
|
||||
name: "Kiosk Demo Disc 2.6"
|
||||
region: "NTSC-U"
|
||||
SCUS-97219:
|
||||
name: "Gran Turismo 3 - A-Spec - Nissan 350Z Edition"
|
||||
@@ -11471,7 +11497,7 @@ SCUS-97226:
|
||||
name: "NCAA GameBreaker 2003 [Demo]"
|
||||
region: "NTSC-U"
|
||||
SCUS-97227:
|
||||
name: "Kiosk Demo Disc 2.07"
|
||||
name: "Kiosk Demo Disc 2.7"
|
||||
region: "NTSC-U"
|
||||
SCUS-97229:
|
||||
name: "Dark Cloud 2 [Demo]"
|
||||
@@ -11574,7 +11600,7 @@ SCUS-97252:
|
||||
name: "Official U.S. PlayStation Magazine Demo Disc 077"
|
||||
region: "NTSC-U"
|
||||
SCUS-97253:
|
||||
name: "NBA Shootout 2003 [Demo]"
|
||||
name: "NBA ShootOut 2003 [Demo]"
|
||||
region: "NTSC-U"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes an issue with loading screens which cause the game to return on the Bios.
|
||||
@@ -11598,7 +11624,7 @@ SCUS-97260:
|
||||
name: "War of the Monsters [Demo]"
|
||||
region: "NTSC-U"
|
||||
SCUS-97261:
|
||||
name: "Kiosk Demo Disc 2.08"
|
||||
name: "Kiosk Demo Disc 2.8"
|
||||
region: "NTSC-U"
|
||||
SCUS-97262:
|
||||
name: "Amplitude [Demo]"
|
||||
@@ -11658,7 +11684,7 @@ SCUS-97269:
|
||||
region: "NTSC-U"
|
||||
compat: 3
|
||||
SCUS-97270:
|
||||
name: "Kiosk Demo Disc 2.09"
|
||||
name: "Kiosk Demo Disc 2.9"
|
||||
region: "NTSC-U"
|
||||
SCUS-97271:
|
||||
name: "Final Fantasy XI - Online [Beta Version] [Disc 1 of 2]"
|
||||
@@ -11718,9 +11744,6 @@ SCUS-97282:
|
||||
halfPixelOffset: 4 # Fixes post-processing alignment.
|
||||
nativeScaling: 1 # Fixes depth blur intensity.
|
||||
textureInsideRT: 1 # Fixes on screen garbage.
|
||||
SCUS-97292:
|
||||
name: "Amplitude [Demo]"
|
||||
region: "NTSC-U"
|
||||
SCUS-97312:
|
||||
name: "Jampack Demo Disc - Winter 2003 [T-Rated]"
|
||||
region: "NTSC-U"
|
||||
@@ -11750,7 +11773,7 @@ SCUS-97319:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SCUS-97321:
|
||||
name: "Kiosk Demo Disc 2.10"
|
||||
name: "Kiosk June·July·August 2003" # Kiosk Demo Disc 2.10 or "PS2-10"
|
||||
region: "NTSC-U"
|
||||
SCUS-97322:
|
||||
name: "Ratchet & Clank 2 - Going Commando [Regular Demo]"
|
||||
@@ -11771,10 +11794,10 @@ SCUS-97323:
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 1 # Fixes light blooms.
|
||||
SCUS-97324:
|
||||
name: "Kiosk Demo Disc 2.11"
|
||||
name: "Kiosk 2-11 Winter 2003" # Kiosk Demo Disc 2.11
|
||||
region: "NTSC-U"
|
||||
SCUS-97325:
|
||||
name: "NBA Shootout 2004 [Demo]"
|
||||
name: "NBA ShootOut 2004 [Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken player rendering and skin flashing.
|
||||
@@ -11908,6 +11931,8 @@ SCUS-97362:
|
||||
SCUS-97365:
|
||||
name: "World Tour Soccer 2005"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCUS-97366:
|
||||
name: "SOCOM II - U.S. Navy SEALs [Public Beta v1.0]"
|
||||
region: "NTSC-U"
|
||||
@@ -11983,13 +12008,13 @@ SCUS-97381:
|
||||
halfPixelOffset: 4 # Aligns post bloom.
|
||||
nativeScaling: 1 # Fixes light blooms.
|
||||
SCUS-97382:
|
||||
name: "NBA Shootout 2004 [Demo]"
|
||||
name: "NBA ShootOut 2004 [Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken player rendering and skin flashing.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
SCUS-97383:
|
||||
name: "Kiosk Demo Disc 2.12"
|
||||
name: "Kiosk 2-12 Spring 2004" # Kiosk Demo Disc 2.12
|
||||
region: "NTSC-U"
|
||||
SCUS-97384:
|
||||
name: "Gran Turismo Special Edition 2004 Toyota [Demo]"
|
||||
@@ -12011,6 +12036,8 @@ SCUS-97395:
|
||||
SCUS-97396:
|
||||
name: "World Tour Soccer 2005 [Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
SCUS-97397:
|
||||
name: "Syphon Filter - The Omega Strain"
|
||||
region: "NTSC-U"
|
||||
@@ -18859,7 +18886,7 @@ SLES-51879:
|
||||
name: "Hot Wheels World Race"
|
||||
region: "PAL-E"
|
||||
SLES-51881:
|
||||
name: "Mercedes Bens World Racing"
|
||||
name: "World Racing"
|
||||
region: "PAL-F-G"
|
||||
SLES-51883:
|
||||
name: "Scooby-Doo! Mystery Mayhem"
|
||||
@@ -19970,6 +19997,10 @@ SLES-52342:
|
||||
name: "Worms Forts - Under Siege"
|
||||
region: "PAL-E-F"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
PCRTCOverscan: 1 # Centers game output.
|
||||
SLES-52343:
|
||||
name: "Midway Arcade Treasures"
|
||||
region: "PAL-E"
|
||||
@@ -21168,6 +21199,10 @@ SLES-52733:
|
||||
SLES-52734:
|
||||
name: "Worms Forts - Under Siege"
|
||||
region: "PAL-M5"
|
||||
gameFixes:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
PCRTCOverscan: 1 # Centers game output.
|
||||
SLES-52737:
|
||||
name: "Obscure"
|
||||
region: "PAL-E"
|
||||
@@ -23268,6 +23303,8 @@ SLES-53458:
|
||||
name: "Shin Megami Tensei - Digital Devil Saga"
|
||||
region: "PAL-E"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SLES-53459:
|
||||
name: "Marc Ecko's Getting Up - Contents Under Pressure"
|
||||
region: "PAL-M5"
|
||||
@@ -25480,10 +25517,13 @@ SLES-54138:
|
||||
name: "Steambot Chronicles"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLES-54139:
|
||||
name: "Earache - Extreme Metal Racing"
|
||||
region: "PAL-E"
|
||||
@@ -26138,10 +26178,13 @@ SLES-54335:
|
||||
name: "Steambot Chronicles"
|
||||
region: "PAL-F"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLES-54336:
|
||||
name: "Lumines Plus"
|
||||
region: "PAL-M5"
|
||||
@@ -27019,8 +27062,13 @@ SLES-54587:
|
||||
name: "Raw Danger"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLES-54588:
|
||||
name: "Brunswick Pro Bowling"
|
||||
region: "PAL-E"
|
||||
@@ -29760,9 +29808,6 @@ SLES-55415:
|
||||
SLES-55418:
|
||||
name: "Tube Mania"
|
||||
region: "PAL-F-DU"
|
||||
SLES-55421:
|
||||
name: "Buzz! Brain of Switzerland"
|
||||
region: "PAL-SWI"
|
||||
SLES-55428:
|
||||
name: "Disney Bolt"
|
||||
region: "PAL-SC"
|
||||
@@ -32381,6 +32426,8 @@ SLKA-25300:
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SLKA-25301:
|
||||
name: "디지털 데빌 사가: 아바탈 튜너 2" # Undumped on ReDump as of 2025-08-28
|
||||
name-en: "Digital Devil Saga - Avatar Tuner 2"
|
||||
@@ -34363,7 +34410,7 @@ SLPM-55163:
|
||||
SLPM-55164:
|
||||
name: "Myself;Yourself [Yeti Best]"
|
||||
name-sort: "まいせるふ ゆあせるふ [Yeti Best]"
|
||||
name-en: "Myself, Yourself [Yeti Best]"
|
||||
name-en: "Myself; Yourself [Yeti Best]"
|
||||
region: "NTSC-J"
|
||||
SLPM-55165:
|
||||
name: "SuperLite 2000 アドベンチャー アオイシロ"
|
||||
@@ -35679,28 +35726,39 @@ SLPM-60253:
|
||||
name-en: "Zettai Zetsumei Toshi 2 - Itetsuita Kioutachi [Trial Type-B]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_ZettaiZetsumeiToshi2"
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPM-60254:
|
||||
name: "絶体絶命都市2 -凍てついた記憶たち- [体験版l Type-A]"
|
||||
name-sort: "ぜったいぜつめいとし2 -いてついたきおくたち- [たいけんばん Type-A]"
|
||||
name-en: "Zettai Zetsumei Toshi 2 - Itetsuita Kioutachi [Trial Type-A]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_ZettaiZetsumeiToshi2"
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPM-60255:
|
||||
name: "ポンコツ浪漫大活劇バンピートロット [体験版]"
|
||||
name-sort: "ぽんこつろまんだいかつげきばんぴーとろっと [たいけんばん]"
|
||||
name-en: "Ponkotsu Roeman Daikatsugeki Bumpy Trot [Trial]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPM-60256:
|
||||
name: "電撃PS2 / 電撃PlayStation D73"
|
||||
name-sort: "でんげき PS2 でんげきPlayStation D73"
|
||||
@@ -35765,10 +35823,13 @@ SLPM-60266:
|
||||
name-en: "Ponkotsu Roeman Daikatsugeki Bumpy Trot [Trial]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPM-60267:
|
||||
name: "餓狼伝 Breakblow [体験版]"
|
||||
name-sort: "がろうでん Breakblow [たいけんばん]"
|
||||
@@ -35819,8 +35880,13 @@ SLPM-60273:
|
||||
name-en: "Zettai Zetsumei Toshi 2 - Itetsuita Kioutachi [Trial Type-B]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuCLUTRender: 1 # Fixes some shading/shadows.
|
||||
getSkipCount: "GSC_ZettaiZetsumeiToshi2"
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPM-60274:
|
||||
name: "フルハウスキス2 [体験版]"
|
||||
name-sort: "ふるはうすきす2 [たいけんばん]"
|
||||
@@ -37627,7 +37693,7 @@ SLPM-62188:
|
||||
SLPM-62190:
|
||||
name: "ハイヒートメジャーリーグベースボール 2003"
|
||||
name-sort: "はいひーとめじゃーりーぐべーすぼーる 2003"
|
||||
name-en: "High Heat - Major League Baseball 2003"
|
||||
name-en: "High Heat Major League Baseball 2003"
|
||||
region: "NTSC-J"
|
||||
SLPM-62192:
|
||||
name: "実況パワフルプロ野球 9"
|
||||
@@ -44249,6 +44315,8 @@ SLPM-65597:
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SLPM-65598:
|
||||
name: "転生學園 幻蒼録"
|
||||
name-sort: "てんしょうがくえん げんそうろく"
|
||||
@@ -48995,6 +49063,8 @@ SLPM-66372:
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SLPM-66373:
|
||||
name: "DIGITAL DEVIL SAGA ~アバタール・チューナー2~ [ATLUS BEST COLLECTION]"
|
||||
name-sort: "でじたるでびるさーが あばたーるちゅーなー2 [ATLUS BEST COLLECTION]"
|
||||
@@ -52229,12 +52299,12 @@ SLPM-66890:
|
||||
SLPM-66891:
|
||||
name: "Myself;Yourself [初回限定版]"
|
||||
name-sort: "まいせるふ ゆあせるふ [しょかいげんていばん]"
|
||||
name-en: "Myself, Yourself [First Limited Edition]"
|
||||
name-en: "Myself; Yourself [First Limited Edition]"
|
||||
region: "NTSC-J"
|
||||
SLPM-66892:
|
||||
name: "Myself;Yourself [通常版]"
|
||||
name-sort: "まいせるふ ゆあせるふ [つうじょうばん]"
|
||||
name-en: "Myself, Yourself [Standard Edition]"
|
||||
name-en: "Myself; Yourself [Standard Edition]"
|
||||
region: "NTSC-J"
|
||||
SLPM-66893:
|
||||
name: "ファイナルファンタジーⅪ ヴァナ・ディール コレクション [プレイオンライン]"
|
||||
@@ -56358,6 +56428,13 @@ SLPS-20443:
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 4 # Fixes water reflections.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-20444:
|
||||
name: "SIMPLE2000シリーズ Vol.90 THE お姉チャンバラ2"
|
||||
name-sort: "しんぷる2000しりーず Vol. 90 THE おねえちゃんばら2"
|
||||
@@ -59041,7 +59118,7 @@ SLPS-25381:
|
||||
SLPS-25382:
|
||||
name: "ワンピース ランドランド!"
|
||||
name-sort: "わんぴーす らんどらんど!"
|
||||
name-en: "One Piece - Land Land"
|
||||
name-en: "One Piece - Land Land!"
|
||||
region: "NTSC-J"
|
||||
SLPS-25383:
|
||||
name: "デジモンバトルクロニクル"
|
||||
@@ -59506,10 +59583,13 @@ SLPS-25457:
|
||||
name-en: "Ponkotsu Roeman Daikatsugeki Bumpy Trot"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25458:
|
||||
name: "THE KING OF FIGHTERS 2001 [SNK BEST COLLECTION]"
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2001 [SNK BEST COLLECTION]"
|
||||
@@ -60169,8 +60249,13 @@ SLPS-25574:
|
||||
name-en: "PachiPara 12 - Ooumi to Natsu no Omoide"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken minimap.
|
||||
cpuSpriteRenderLevel: 1 # Needed for above.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25575:
|
||||
name: "ケロロ軍曹 メロメロバトルロイヤルZ"
|
||||
name-sort: "けろろぐんそう めろめろばとるろいやるZ"
|
||||
@@ -60377,9 +60462,13 @@ SLPS-25606:
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_ZettaiZetsumeiToshi2"
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25607:
|
||||
name: "魔界戦記ディスガイア2 [初回限定版]"
|
||||
name-sort: "まかいせんきでぃすがいあ2 [しょかいげんていばん]"
|
||||
@@ -60885,18 +60974,26 @@ SLPS-25682:
|
||||
name-en: "PachiPara 13 - Super Umi to PachiPro Fu-unroku"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken minimap.
|
||||
cpuSpriteRenderLevel: 1 # Needed for above.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25683:
|
||||
name: "ポンコツ浪漫大活劇バンピートロット [Irem COLLECTION]"
|
||||
name-sort: "ぽんこつろまんだいかつげきばんぴーとろっと [Irem COLLECTION]"
|
||||
name-en: "Ponkotsu Roman Daikatsugeki Bumpy Trot [Irem Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25684:
|
||||
name: "マーメイドプリズム [限定版BOX]"
|
||||
name-sort: "まーめいどぷりずむ [げんていばんBOX]"
|
||||
@@ -61507,8 +61604,13 @@ SLPS-25787:
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken minimap.
|
||||
cpuSpriteRenderLevel: 1 # Needed for above.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25788:
|
||||
name: "メタルスラッグ [SNK BEST COLLECTION]"
|
||||
name-sort: "めたるすらっぐ [SNK BEST COLLECTION]"
|
||||
@@ -61552,8 +61654,11 @@ SLPS-25795:
|
||||
SLPS-25796:
|
||||
name: "俺の下でAGAKE"
|
||||
name-sort: "おれのしたであがけ"
|
||||
name-en: "Ore no Shite Agake"
|
||||
name-en: "Ore no Shita de Agake"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes incorrect rendering and some missing text.
|
||||
cpuCLUTRender: 1 # Fixes the rest of the incorrect rendering and missing text.
|
||||
SLPS-25797:
|
||||
name: "一騎当千 Shining Dragon [限定爆裂パック]"
|
||||
name-sort: "いっきとうせん Shining Dragon [げんていばくれつぱっく]"
|
||||
@@ -61898,17 +62003,26 @@ SLPS-25851:
|
||||
name-en: "Zettai Zetsumei Toshi 2 - Itetsuita Kioku Tachi [Irem Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_ZettaiZetsumeiToshi2"
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25852:
|
||||
name: "パチパラ13 ~スーパー海とパチプロ風雲録~ [Irem COLLECTION]"
|
||||
name-sort: "ぱちぱら13 すーぱーうみとぱちぷろふううんろく [Irem COLLECTION]"
|
||||
name-en: "PachiPara 13 - Super Umi to PachiPro Fu-unroku [Irem Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 2 # Fixes broken minimap.
|
||||
cpuSpriteRenderLevel: 1 # Needed for above.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLPS-25853:
|
||||
name: "パチってちょんまげ達人14 ~ ぱちんこ仮面ライダー ショッカー全滅大作戦"
|
||||
name-sort: "ぱちってちょんまげたつじん14 ~ ぱちんこかめんらいだー しょっかーぜんめつだいさくせん"
|
||||
@@ -64141,7 +64255,7 @@ SLUS-20132:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20133:
|
||||
name: "High Heat Baseball 2002"
|
||||
name: "High Heat Major League Baseball 2002"
|
||||
region: "NTSC-U"
|
||||
SLUS-20134:
|
||||
name: "Sky Odyssey"
|
||||
@@ -64375,10 +64489,6 @@ SLUS-20182:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post effects.
|
||||
autoFlush: 1 # Fixes ghosting.
|
||||
SLUS-20183:
|
||||
name: "Tiny Toon Adventures - Defenders of the Universe"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20184:
|
||||
name: "Resident Evil - CODE Veronica X"
|
||||
region: "NTSC-U"
|
||||
@@ -64913,7 +65023,7 @@ SLUS-20297:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20298:
|
||||
name: "High Heat - Major League Baseball 2003"
|
||||
name: "High Heat Major League Baseball 2003"
|
||||
region: "NTSC-U"
|
||||
SLUS-20299:
|
||||
name: "Street Hoops - King of the Court"
|
||||
@@ -65692,9 +65802,6 @@ SLUS-20443:
|
||||
name: "Rugrats - Royal Ransom"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20444:
|
||||
name: "Tankers - Smoking Barrels"
|
||||
region: "NTSC-U"
|
||||
SLUS-20445:
|
||||
name: "Robot Alchemic Drive - R.A.D."
|
||||
region: "NTSC-U"
|
||||
@@ -66551,7 +66658,7 @@ SLUS-20601:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes missing blur layer on reflections and surfaces.
|
||||
SLUS-20602:
|
||||
name: "High Heat - Major League Baseball 2004"
|
||||
name: "High Heat Major League Baseball 2004"
|
||||
region: "NTSC-U"
|
||||
SLUS-20603:
|
||||
name: "Mary-Kate & Ashley - Sweet Sixteen - Licensed to Drive"
|
||||
@@ -66832,7 +66939,7 @@ SLUS-20657:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20658:
|
||||
name: "Freedom Fighters - The Battle for Liberty Island"
|
||||
name: "Freedom Fighters" # Originally Freedom – The Battle for Liberty Island
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20659:
|
||||
@@ -67070,9 +67177,6 @@ SLUS-20698:
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 2 # Needed for SPS on some characters.
|
||||
SLUS-20699:
|
||||
name: "Cowboy Bebop"
|
||||
region: "NTSC-U"
|
||||
SLUS-20701:
|
||||
name: "Scooby-Doo! Mystery Mayhem"
|
||||
region: "NTSC-U"
|
||||
@@ -67618,9 +67722,6 @@ SLUS-20797:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Fixes misaligned bloom.
|
||||
autoFlush: 2 # Fixes sun occlusion and heat radiosity.
|
||||
SLUS-20798:
|
||||
name: "Starcraft - Ghost"
|
||||
region: "NTSC-U"
|
||||
SLUS-20799:
|
||||
name: "Terminator 3 - Rise of the Machines"
|
||||
region: "NTSC-U"
|
||||
@@ -67683,9 +67784,6 @@ SLUS-20812:
|
||||
name: "Dynasty Warriors 4 - Xtreme Legends"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20813:
|
||||
name: "Plague of Darkness"
|
||||
region: "NTSC-U"
|
||||
SLUS-20814:
|
||||
name: "Max Payne 2 - The Fall of Max Payne"
|
||||
region: "NTSC-U"
|
||||
@@ -68154,9 +68252,6 @@ SLUS-20896:
|
||||
vuClampMode: 3 # Fixes lighting on character models as caves and other locations don't turn mobs into glow-in-the-dark creatures by themselves.
|
||||
gsHWFixes:
|
||||
maximumBlendingLevel: 0 # Fixes unnecessary load on the GPU.
|
||||
SLUS-20897:
|
||||
name: "Swords of Yi"
|
||||
region: "NTSC-U"
|
||||
SLUS-20898:
|
||||
name: "Star Wars - Battlefront"
|
||||
region: "NTSC-U"
|
||||
@@ -68243,7 +68338,7 @@ SLUS-20911:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Fixes bilinear on lighting effects.
|
||||
SLUS-20912:
|
||||
name: "Superbikes TT"
|
||||
name: "Suzuki TT Superbikes - Real Road Racing"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-20913:
|
||||
@@ -68653,6 +68748,8 @@ SLUS-20974:
|
||||
name: "Shin Megami Tensei - Digital Devil Saga"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SLUS-20975:
|
||||
name: "One Piece - Grand Battle"
|
||||
region: "NTSC-U"
|
||||
@@ -69376,6 +69473,8 @@ SLUS-21093:
|
||||
name: "Worms Forts - Under Siege"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
SLUS-21094:
|
||||
name: "Midway Arcade Treasures 3"
|
||||
region: "NTSC-U"
|
||||
@@ -71065,10 +71164,13 @@ SLUS-21344:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLUS-21345:
|
||||
name: "Grandia III [Disc 2 of 2]"
|
||||
region: "NTSC-U"
|
||||
@@ -71944,9 +72046,6 @@ SLUS-21467:
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post effects.
|
||||
SLUS-21468:
|
||||
name: "Charlie Brown's All-Stars [Cancelled]"
|
||||
region: "NTSC-U"
|
||||
SLUS-21469:
|
||||
name: "Nicktoons - Battle for Volcano Island"
|
||||
region: "NTSC-U"
|
||||
@@ -72168,8 +72267,13 @@ SLUS-21501:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns post-processing.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLUS-21503:
|
||||
name: "God Hand"
|
||||
region: "NTSC-U"
|
||||
@@ -73867,7 +73971,7 @@ SLUS-21831:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-21834:
|
||||
name: "Goosebumps Horrorland - Happy Halloween"
|
||||
name: "Goosebumps Horrorland"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
clampModes:
|
||||
@@ -74565,7 +74669,7 @@ SLUS-28027:
|
||||
name: "Black & Bruised [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
SLUS-28029:
|
||||
name: "High Heat - Major League Baseball 2004 [Trade Demo]"
|
||||
name: "High Heat Major League Baseball 2004 [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
SLUS-28031:
|
||||
name: "Auto Modellista - Public Beta Volume 2.0"
|
||||
@@ -74623,6 +74727,8 @@ SLUS-28046:
|
||||
SLUS-28049:
|
||||
name: "Shin Megami Tensei - Digital Devil Saga [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns shadows to prevent artefacts.
|
||||
SLUS-28050:
|
||||
name: "Stella Deus - The Gate of Eternity [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -74655,10 +74761,13 @@ SLUS-28061:
|
||||
name: "Steambot Chronicles [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLUS-28062:
|
||||
name: "Dance Factory [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -74751,7 +74860,7 @@ SLUS-29017:
|
||||
name: "AirBlade [Demo]"
|
||||
region: "NTSC-U"
|
||||
SLUS-29019:
|
||||
name: "High Heat - Major League Baseball 2003 [Demo]"
|
||||
name: "High Heat Major League Baseball 2003 [Demo]"
|
||||
region: "NTSC-U"
|
||||
SLUS-29020:
|
||||
name: "Sky Gunner [Regular Demo]"
|
||||
@@ -75426,10 +75535,13 @@ SLUS-29188:
|
||||
name: "Steambot Chronicles [Regular Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_SteambotChronicles" # Causes green (incorrect) water but removes depth and blur issues.
|
||||
roundSprite: 1 # Fixes colored 3D anaglyph bleeding effects.
|
||||
halfPixelOffset: 5 # Aligns effects.
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
nativeScaling: 1 # Helps align effects.
|
||||
textureInsideRT: 1 # Fixes channel shuffles.
|
||||
preloadFrameData: 1 # Fixes menu graphics.
|
||||
autoFlush: 1 # Fixes motion blur.
|
||||
minimumBlendingLevel: 2 # Improves post effects.
|
||||
SLUS-29189:
|
||||
name: "FIFA World Cup - Germany 2006 [Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -75505,12 +75617,6 @@ SLUS-29201:
|
||||
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
|
||||
nativeScaling: 1 # Fixes misaligned bloom.
|
||||
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
|
||||
SLUS-80421:
|
||||
name: "Resident Evil 2 [Demo]"
|
||||
region: "NTSC-U"
|
||||
SLUS-90009:
|
||||
name: "Resident Evil 2 [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
SLUS-97405:
|
||||
name: "ATV Offroad Fury 3"
|
||||
region: "NTSC-U"
|
||||
@@ -75524,7 +75630,9 @@ TCES-10001:
|
||||
region: "PAL-E"
|
||||
TCES-51613:
|
||||
name: "This Is Football 2004 Beta Trial Code"
|
||||
region: "PAL-E-S"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
PCRTCOffsets: 1 # Fixes boot videos screen size.
|
||||
TCES-51904:
|
||||
name: "SOCOM II - U.S. Navy SEALs Beta Trial Code"
|
||||
region: "PAL-M5"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Game Controller DB for SDL in 2.0.16 format
|
||||
# Source: https://github.com/gabomdq/SDL_GameControllerDB
|
||||
# Source: https://github.com/mdqinc/SDL_GameControllerDB
|
||||
|
||||
# Windows
|
||||
03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
|
||||
@@ -253,7 +253,6 @@
|
||||
03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -1197,6 +1196,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00000960000011010000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
@@ -1331,6 +1331,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000f0250000c283000010010000,Gioteck VX2 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux,
|
||||
190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux,
|
||||
|
||||
BIN
bin/resources/icons/AppIconLarge.ico
Normal file
BIN
bin/resources/icons/AppIconLarge.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
@@ -80,6 +80,7 @@ PS_OUTPUT ps_downsample_copy(PS_INPUT input)
|
||||
int DownsampleFactor = DOFFSET;
|
||||
int2 ClampMin = int2(EMODA, EMODC);
|
||||
float Weight = BGColor.x;
|
||||
float step_multiplier = BGColor.y;
|
||||
|
||||
int2 coord = max(int2(input.p.xy) * DownsampleFactor, ClampMin);
|
||||
|
||||
@@ -88,7 +89,7 @@ PS_OUTPUT ps_downsample_copy(PS_INPUT input)
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
output.c += Texture.Load(int3(coord + int2(xoff, yoff), 0));
|
||||
output.c += Texture.Load(int3(coord + int2(xoff * step_multiplier, yoff * step_multiplier), 0));
|
||||
}
|
||||
output.c /= Weight;
|
||||
return output;
|
||||
|
||||
@@ -175,8 +175,32 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
|
||||
// high motion -> interpolate pixels above and below
|
||||
return (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
return cn;
|
||||
{
|
||||
// Check if it's completely static first, we don't need to mess with any of that.
|
||||
if((mh_max != -motion_thr.x) || (ml_max != -motion_thr.x) || (mc_max != -motion_thr.x))
|
||||
{
|
||||
// Check the diff with the above and below lines, if the difference is smaller between the new high and low lines
|
||||
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
|
||||
float3 mhln = hn.rgb - ln.rgb;
|
||||
float3 mchn = hn.rgb - cn.rgb;
|
||||
|
||||
mhln = max(mhln, -mhln) - motion_thr;
|
||||
mchn = max(mchn, -mchn) - motion_thr;
|
||||
|
||||
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
|
||||
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
|
||||
|
||||
// The new centre line is a fair chunk different from those surrounding it, so quite likely incorrect.
|
||||
if (mhln_max < 0.0f && mchn_max >= (mhln_max * 0.90f))
|
||||
return (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
return cn;
|
||||
}
|
||||
else
|
||||
// low motion -> weave
|
||||
return cn;
|
||||
}
|
||||
}
|
||||
|
||||
return float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
@@ -70,6 +70,7 @@ void ps_depth_copy()
|
||||
uniform ivec2 ClampMin;
|
||||
uniform int DownsampleFactor;
|
||||
uniform float Weight;
|
||||
uniform float StepMultiplier;
|
||||
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
@@ -78,7 +79,7 @@ void ps_downsample_copy()
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(TextureSampler, coord + ivec2(xoff, yoff), 0);
|
||||
result += texelFetch(TextureSampler, coord + ivec2(xoff * StepMultiplier, yoff * StepMultiplier), 0);
|
||||
}
|
||||
SV_Target0 = result / Weight;
|
||||
}
|
||||
|
||||
@@ -173,8 +173,32 @@ void ps_main4()
|
||||
// high motion -> interpolate pixels above and below
|
||||
SV_Target0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
SV_Target0 = cn;
|
||||
{
|
||||
// Check if it's completely static first, we don't need to mess with any of that.
|
||||
if((mh_max != -motion_thr.x) || (ml_max != -motion_thr.x) || (mc_max != -motion_thr.x))
|
||||
{
|
||||
// Check the diff with the above and below lines, if the difference is smaller between the new high and low lines
|
||||
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
|
||||
vec3 mhln = hn.rgb - ln.rgb;
|
||||
vec3 mchn = hn.rgb - cn.rgb;
|
||||
|
||||
mhln = max(mhln, -mhln) - motion_thr;
|
||||
mchn = max(mchn, -mchn) - motion_thr;
|
||||
|
||||
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
|
||||
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
|
||||
|
||||
// The new centre line is a fair chunk different from those surrounding it, so quite likely incorrect.
|
||||
if (mhln_max < 0.0f && mchn_max >= (mhln_max * 0.90f))
|
||||
SV_Target0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
else
|
||||
// low motion -> weave
|
||||
SV_Target0 = cn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@ layout(push_constant) uniform cb10
|
||||
int DownsampleFactor;
|
||||
int pad0;
|
||||
float Weight;
|
||||
vec3 pad1;
|
||||
float step_multiplier;
|
||||
vec2 pad1;
|
||||
};
|
||||
void ps_downsample_copy()
|
||||
{
|
||||
@@ -75,7 +76,9 @@ void ps_downsample_copy()
|
||||
for (int yoff = 0; yoff < DownsampleFactor; yoff++)
|
||||
{
|
||||
for (int xoff = 0; xoff < DownsampleFactor; xoff++)
|
||||
result += texelFetch(samp0, coord + ivec2(xoff, yoff), 0);
|
||||
{
|
||||
result += texelFetch(samp0, coord + ivec2(xoff * step_multiplier, yoff * step_multiplier), 0);
|
||||
}
|
||||
}
|
||||
o_col0 = result / Weight;
|
||||
}
|
||||
|
||||
@@ -194,8 +194,32 @@ void ps_main4()
|
||||
// high motion -> interpolate pixels above and below
|
||||
o_col0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
o_col0 = cn;
|
||||
{
|
||||
// Check if it's completely static first, we don't need to mess with any of that.
|
||||
if((mh_max != -motion_thr.x) || (ml_max != -motion_thr.x) || (mc_max != -motion_thr.x))
|
||||
{
|
||||
// Check the diff with the above and below lines, if the difference is smaller between the new high and low lines
|
||||
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
|
||||
vec3 mhln = hn.rgb - ln.rgb;
|
||||
vec3 mchn = hn.rgb - cn.rgb;
|
||||
|
||||
mhln = max(mhln, -mhln) - motion_thr;
|
||||
mchn = max(mchn, -mchn) - motion_thr;
|
||||
|
||||
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
|
||||
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
|
||||
|
||||
// The new centre line is a fair chunk different from those surrounding it, so quite likely incorrect.
|
||||
if (mhln_max < 0.0f && mchn_max >= (mhln_max * 0.90f))
|
||||
o_col0 = (hn + ln) / 2.0f;
|
||||
else
|
||||
// low motion -> weave
|
||||
o_col0 = cn;
|
||||
}
|
||||
else
|
||||
// low motion -> weave
|
||||
o_col0 = cn;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -108,7 +108,7 @@ disable_compiler_warnings_for_target(speex)
|
||||
|
||||
# Find the Qt components that we need.
|
||||
if(ENABLE_QT_UI)
|
||||
find_package(Qt6 6.7.3 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
|
||||
find_package(Qt6 6.10.0 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
|
||||
endif()
|
||||
|
||||
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.10.0)
|
||||
|
||||
@@ -7,7 +7,6 @@ endif(NOT TOP_CMAKE_WAS_SOURCED)
|
||||
|
||||
add_library(common)
|
||||
|
||||
# x86emitter sources
|
||||
target_sources(common PRIVATE
|
||||
AlignedMalloc.cpp
|
||||
Assertions.cpp
|
||||
@@ -34,9 +33,9 @@ target_sources(common PRIVATE
|
||||
Timer.cpp
|
||||
WAVWriter.cpp
|
||||
WindowInfo.cpp
|
||||
YAML.cpp
|
||||
)
|
||||
|
||||
# x86emitter headers
|
||||
target_sources(common PRIVATE
|
||||
AlignedMalloc.h
|
||||
Assertions.h
|
||||
@@ -81,6 +80,7 @@ target_sources(common PRIVATE
|
||||
WAVWriter.h
|
||||
WindowInfo.h
|
||||
WrappedMemCopy.h
|
||||
YAML.h
|
||||
)
|
||||
|
||||
if(_M_X86)
|
||||
@@ -208,6 +208,7 @@ target_link_libraries(common PRIVATE
|
||||
target_link_libraries(common PUBLIC
|
||||
fmt::fmt
|
||||
fast_float
|
||||
rapidyaml::rapidyaml
|
||||
)
|
||||
|
||||
fixup_file_properties(common)
|
||||
|
||||
@@ -15,10 +15,6 @@ namespace CocoaTools
|
||||
void DestroyMetalLayer(WindowInfo* wi);
|
||||
std::optional<float> GetViewRefreshRate(const WindowInfo& wi);
|
||||
|
||||
/// Add a handler to be run when macOS changes between dark and light themes
|
||||
void AddThemeChangeHandler(void* ctx, void(handler)(void* ctx));
|
||||
/// Remove a handler previously added using AddThemeChangeHandler with the given context
|
||||
void RemoveThemeChangeHandler(void* ctx);
|
||||
/// Mark an NSMenu as the help menu
|
||||
void MarkHelpMenu(void* menu);
|
||||
/// Returns the bundle path.
|
||||
@@ -44,6 +40,6 @@ namespace CocoaTools
|
||||
void RunCocoaEventLoop(bool wait_forever = false);
|
||||
/// Posts an event to the main telling `RunCocoaEventLoop(true)` to exit
|
||||
void StopMainThreadEventLoop();
|
||||
}
|
||||
} // namespace CocoaTools
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
@@ -85,63 +85,7 @@ std::optional<float> CocoaTools::GetViewRefreshRate(const WindowInfo& wi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// MARK: - Theme Change Handlers
|
||||
|
||||
@interface PCSX2KVOHelper : NSObject
|
||||
|
||||
- (void)addCallback:(void*)ctx run:(void(*)(void*))callback;
|
||||
- (void)removeCallback:(void*)ctx;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PCSX2KVOHelper
|
||||
{
|
||||
std::vector<std::pair<void*, void(*)(void*)>> _callbacks;
|
||||
}
|
||||
|
||||
- (void)addCallback:(void*)ctx run:(void(*)(void*))callback
|
||||
{
|
||||
_callbacks.push_back(std::make_pair(ctx, callback));
|
||||
}
|
||||
|
||||
- (void)removeCallback:(void*)ctx
|
||||
{
|
||||
auto new_end = std::remove_if(_callbacks.begin(), _callbacks.end(), [ctx](const auto& entry){
|
||||
return ctx == entry.first;
|
||||
});
|
||||
_callbacks.erase(new_end, _callbacks.end());
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
|
||||
{
|
||||
for (const auto& callback : _callbacks)
|
||||
callback.second(callback.first);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static PCSX2KVOHelper* s_themeChangeHandler;
|
||||
|
||||
void CocoaTools::AddThemeChangeHandler(void* ctx, void(handler)(void* ctx))
|
||||
{
|
||||
assert([NSThread isMainThread]);
|
||||
if (!s_themeChangeHandler)
|
||||
{
|
||||
s_themeChangeHandler = [[PCSX2KVOHelper alloc] init];
|
||||
NSApplication* app = [NSApplication sharedApplication];
|
||||
[app addObserver:s_themeChangeHandler
|
||||
forKeyPath:@"effectiveAppearance"
|
||||
options:0
|
||||
context:nil];
|
||||
}
|
||||
[s_themeChangeHandler addCallback:ctx run:handler];
|
||||
}
|
||||
|
||||
void CocoaTools::RemoveThemeChangeHandler(void* ctx)
|
||||
{
|
||||
assert([NSThread isMainThread]);
|
||||
[s_themeChangeHandler removeCallback:ctx];
|
||||
}
|
||||
// MARK: - Help menu
|
||||
|
||||
void CocoaTools::MarkHelpMenu(void* menu)
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ static inline bool FileSystemCharacterIsSane(char32_t c, bool strip_slashes)
|
||||
if (c == '*')
|
||||
return false;
|
||||
|
||||
// macos doesn't allow colons, apparently
|
||||
// macos doesn't allow colons, apparently
|
||||
#ifdef __APPLE__
|
||||
if (c == U':')
|
||||
return false;
|
||||
@@ -2490,6 +2490,21 @@ bool FileSystem::DeleteDirectory(const char* path)
|
||||
return (rmdir(path) == 0);
|
||||
}
|
||||
|
||||
std::string FileSystem::GetPackagePath()
|
||||
{
|
||||
// NOTE: The reason this function is separated from FileSystem::GetProgramPath() is because
|
||||
// This path check breaks other usages of FileSystem::GetProgramPath for the AppImage.
|
||||
// Notably the CI-generated AppImage fails to start because PCSX2 can't find its resources
|
||||
// since it tries to look for them relative to the .AppImage file instead of relative to the actual executable.
|
||||
|
||||
// Check if we are running inside appimage. If so, return the path to the appimage instead.
|
||||
if (const char* appimage_path = getenv("APPIMAGE"))
|
||||
return std::string(appimage_path);
|
||||
|
||||
// Otherwise, find the executable file directly
|
||||
return GetProgramPath();
|
||||
}
|
||||
|
||||
std::string FileSystem::GetProgramPath()
|
||||
{
|
||||
#if defined(__linux__)
|
||||
|
||||
@@ -166,6 +166,9 @@ namespace FileSystem
|
||||
/// Copies one file to another, optionally replacing it if it already exists.
|
||||
bool CopyFilePath(const char* source, const char* destination, bool replace);
|
||||
|
||||
/// Returns the path to the current package (AppImage).
|
||||
std::string GetPackagePath();
|
||||
|
||||
/// Returns the path to the current executable.
|
||||
std::string GetProgramPath();
|
||||
|
||||
|
||||
620
common/Image.cpp
620
common/Image.cpp
@@ -32,6 +32,11 @@ static bool WebPBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8
|
||||
static bool WebPFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||
static bool WebPFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality);
|
||||
|
||||
static bool BMPBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
||||
static bool BMPBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality);
|
||||
static bool BMPFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||
static bool BMPFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality);
|
||||
|
||||
struct FormatHandler
|
||||
{
|
||||
const char* extension;
|
||||
@@ -46,6 +51,7 @@ static constexpr FormatHandler s_format_handlers[] = {
|
||||
{"jpg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
||||
{"jpeg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
||||
{"webp", WebPBufferLoader, WebPBufferSaver, WebPFileLoader, WebPFileSaver},
|
||||
{"bmp", BMPBufferLoader, BMPBufferSaver, BMPFileLoader, BMPFileSaver},
|
||||
};
|
||||
|
||||
static const FormatHandler* GetFormatHandler(const std::string_view extension)
|
||||
@@ -734,3 +740,617 @@ bool WebPFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp,
|
||||
|
||||
return (std::fwrite(buffer.data(), buffer.size(), 1, fp) == 1);
|
||||
}
|
||||
|
||||
// Some of this code is adapted from Qt's BMP handler (https://github.com/qt/qtbase/blob/dev/src/gui/image/qbmphandler.cpp)
|
||||
#pragma pack(push, 1)
|
||||
struct BMPFileHeader
|
||||
{
|
||||
u16 type;
|
||||
u32 size;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct BMPInfoHeader
|
||||
{
|
||||
u32 size;
|
||||
s32 width;
|
||||
s32 height;
|
||||
u16 planes;
|
||||
u16 bit_count;
|
||||
u32 compression;
|
||||
u32 size_image;
|
||||
s32 x_pels_per_meter;
|
||||
s32 y_pels_per_meter;
|
||||
u32 clr_used;
|
||||
u32 clr_important;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool IsSupportedBMPFormat(u32 compression, u16 bit_count)
|
||||
{
|
||||
if (compression == 0)
|
||||
return (bit_count == 1 || bit_count == 4 || bit_count == 8 || bit_count == 16 || bit_count == 24 || bit_count == 32);
|
||||
|
||||
if (compression == 1)
|
||||
return (bit_count == 8);
|
||||
|
||||
if (compression == 2)
|
||||
return (bit_count == 4);
|
||||
|
||||
if (compression == 3 || compression == 4) // BMP_BITFIELDS or BMP_ALPHABITFIELDS
|
||||
return (bit_count == 16 || bit_count == 32);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadBMPPalette(std::vector<u32>& palette, const u8* data, u32 palette_offset, const BMPInfoHeader& info_header)
|
||||
{
|
||||
// 1 bit format doesn't use a palette in the traditional sense
|
||||
if (info_header.bit_count == 1)
|
||||
{
|
||||
palette = {0xFFFFFFFF, 0xFF000000};
|
||||
return true;
|
||||
}
|
||||
|
||||
const u32 num_colors = (info_header.clr_used > 0) ? info_header.clr_used : (1u << info_header.bit_count);
|
||||
|
||||
// Make sure that we don't have an unreasonably large palette
|
||||
if (num_colors > 256)
|
||||
{
|
||||
Console.Error("Invalid palette size: %u", num_colors);
|
||||
return false;
|
||||
}
|
||||
|
||||
palette.clear();
|
||||
palette.reserve(num_colors);
|
||||
|
||||
const u8* palette_data = data + sizeof(BMPFileHeader) + info_header.size;
|
||||
|
||||
for (u32 i = 0; i < num_colors; i++)
|
||||
{
|
||||
const u8* color = palette_data + (i * 4);
|
||||
const u8 b = color[0];
|
||||
const u8 g = color[1];
|
||||
const u8 r = color[2];
|
||||
palette.push_back(r | (g << 8) | (b << 16) | 0xFF000000u);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadUncompressedBMP(u32* pixels, const u8* src, const u8* data, u32 width, u32 height, const BMPInfoHeader& info_header, const std::vector<u32>& palette, bool flip_vertical, u32 red_mask = 0, u32 green_mask = 0, u32 blue_mask = 0, u32 alpha_mask = 0, bool use_alpha = false)
|
||||
{
|
||||
const u32 row_size = ((width * info_header.bit_count + 31) / 32) * 4;
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
u32 dst_y = flip_vertical ? (height - 1 - y) : y;
|
||||
const u8* row_src = src + (y * row_size);
|
||||
u32* row_dst = pixels + (dst_y * width);
|
||||
|
||||
u32 bit_offset = 0;
|
||||
|
||||
for (u32 x = 0; x < width; x++)
|
||||
{
|
||||
u32 pixel_value = 0;
|
||||
|
||||
switch (info_header.bit_count)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
const u32 byte_index = bit_offset / 8;
|
||||
const u32 bit_index = 7 - (bit_offset % 8);
|
||||
pixel_value = (row_src[byte_index] >> bit_index) & 1;
|
||||
bit_offset += 1;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
const u32 byte_index = bit_offset / 8;
|
||||
const u32 nibble_index = (bit_offset % 8) / 4;
|
||||
pixel_value = (row_src[byte_index] >> (nibble_index * 4)) & 0xF;
|
||||
bit_offset += 4;
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
pixel_value = row_src[bit_offset / 8];
|
||||
bit_offset += 8;
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
const u32 byte_index = bit_offset / 8;
|
||||
pixel_value = row_src[byte_index] | (row_src[byte_index + 1] << 8);
|
||||
bit_offset += 16;
|
||||
|
||||
if (info_header.compression == 3)
|
||||
{
|
||||
const u8* bitfields = data + sizeof(BMPFileHeader) + info_header.size;
|
||||
const u32 r_mask = *reinterpret_cast<const u32*>(bitfields);
|
||||
const u32 g_mask = *reinterpret_cast<const u32*>(bitfields + 4);
|
||||
const u32 b_mask = *reinterpret_cast<const u32*>(bitfields + 8);
|
||||
|
||||
u32 r_shift = 0, g_shift = 0, b_shift = 0;
|
||||
u32 temp = r_mask;
|
||||
while (temp >>= 1)
|
||||
r_shift++;
|
||||
temp = g_mask;
|
||||
while (temp >>= 1)
|
||||
g_shift++;
|
||||
temp = b_mask;
|
||||
while (temp >>= 1)
|
||||
b_shift++;
|
||||
|
||||
const u8 r = static_cast<u8>((pixel_value & r_mask) >> r_shift);
|
||||
const u8 g = static_cast<u8>((pixel_value & g_mask) >> g_shift);
|
||||
const u8 b = static_cast<u8>((pixel_value & b_mask) >> b_shift);
|
||||
|
||||
const u8 r_max = static_cast<u8>(r_mask >> r_shift);
|
||||
const u8 g_max = static_cast<u8>(g_mask >> g_shift);
|
||||
const u8 b_max = static_cast<u8>(b_mask >> b_shift);
|
||||
|
||||
const u8 r_scaled = (r_max > 0) ? static_cast<u8>((r * 255) / r_max) : 0;
|
||||
const u8 g_scaled = (g_max > 0) ? static_cast<u8>((g * 255) / g_max) : 0;
|
||||
const u8 b_scaled = (b_max > 0) ? static_cast<u8>((b * 255) / b_max) : 0;
|
||||
|
||||
row_dst[x] = r_scaled | (g_scaled << 8) | (b_scaled << 16) | 0xFF000000u;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8 r = (pixel_value >> 10) & 0x1F;
|
||||
const u8 g = (pixel_value >> 5) & 0x1F;
|
||||
const u8 b = pixel_value & 0x1F;
|
||||
row_dst[x] = (r << 3) | (g << 11) | (b << 19) | 0xFF000000u;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case 24:
|
||||
{
|
||||
const u32 byte_index = bit_offset / 8;
|
||||
const u8 b = row_src[byte_index + 0];
|
||||
const u8 g = row_src[byte_index + 1];
|
||||
const u8 r = row_src[byte_index + 2];
|
||||
row_dst[x] = r | (g << 8) | (b << 16) | 0xFF000000u;
|
||||
bit_offset += 24;
|
||||
continue;
|
||||
}
|
||||
case 32:
|
||||
{
|
||||
const u32 byte_index = bit_offset / 8;
|
||||
u32 pixel_value = row_src[byte_index] | (row_src[byte_index + 1] << 8) | (row_src[byte_index + 2] << 16) | (row_src[byte_index + 3] << 24);
|
||||
bit_offset += 32;
|
||||
|
||||
if (info_header.compression == 3 || info_header.compression == 4) // BITFIELDS or ALPHABITFIELDS
|
||||
{
|
||||
// Calculate shifts
|
||||
auto calc_shift = [](u32 mask) -> u32 {
|
||||
u32 result = 0;
|
||||
while ((mask >= 0x100) || (!(mask & 1) && mask))
|
||||
{
|
||||
result++;
|
||||
mask >>= 1;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// Calculate scales
|
||||
auto calc_scale = [](u32 low_mask) -> u32 {
|
||||
u32 result = 8;
|
||||
while (low_mask && result)
|
||||
{
|
||||
result--;
|
||||
low_mask >>= 1;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// Apply scale
|
||||
auto apply_scale = [](u32 value, u32 scale) -> u8 {
|
||||
if (!(scale & 0x07)) // scale == 8 or 0
|
||||
return static_cast<u8>(value);
|
||||
u32 filled = 8 - scale;
|
||||
u32 result = value << scale;
|
||||
do
|
||||
{
|
||||
result |= result >> filled;
|
||||
filled <<= 1;
|
||||
} while (filled < 8);
|
||||
return static_cast<u8>(result);
|
||||
};
|
||||
|
||||
const u32 r_shift = calc_shift(red_mask);
|
||||
const u32 g_shift = calc_shift(green_mask);
|
||||
const u32 b_shift = calc_shift(blue_mask);
|
||||
const u32 a_shift = (alpha_mask != 0) ? calc_shift(alpha_mask) : 0;
|
||||
|
||||
const u32 r_scale = calc_scale(red_mask >> r_shift);
|
||||
const u32 g_scale = calc_scale(green_mask >> g_shift);
|
||||
const u32 b_scale = calc_scale(blue_mask >> b_shift);
|
||||
const u32 a_scale = (alpha_mask != 0) ? calc_scale(alpha_mask >> a_shift) : 0;
|
||||
|
||||
const u8 r = apply_scale((pixel_value & red_mask) >> r_shift, r_scale);
|
||||
const u8 g = apply_scale((pixel_value & green_mask) >> g_shift, g_scale);
|
||||
const u8 b = apply_scale((pixel_value & blue_mask) >> b_shift, b_scale);
|
||||
const u8 a = (use_alpha && alpha_mask != 0) ? apply_scale((pixel_value & alpha_mask) >> a_shift, a_scale) : 0xFF;
|
||||
|
||||
row_dst[x] = r | (g << 8) | (b << 16) | (a << 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Uncompressed 32-bit BGRA order
|
||||
const u8 b = row_src[byte_index + 0];
|
||||
const u8 g = row_src[byte_index + 1];
|
||||
const u8 r = row_src[byte_index + 2];
|
||||
const u8 a = row_src[byte_index + 3];
|
||||
row_dst[x] = r | (g << 8) | (b << 16) | (a << 24);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (info_header.bit_count <= 8)
|
||||
{
|
||||
if (pixel_value < palette.size())
|
||||
row_dst[x] = palette[pixel_value];
|
||||
else
|
||||
{
|
||||
Console.Error("Invalid palette index: %u (palette size: %zu)", pixel_value, palette.size());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadCompressedBMP(u32* pixels, const u8* src, u32 src_size, u32 width, u32 height, const BMPInfoHeader& info_header, const std::vector<u32>& palette, bool flip_vertical)
|
||||
{
|
||||
u32 src_pos = 0;
|
||||
const u32 pixel_size = (info_header.bit_count == 8) ? 1 : 2;
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
u32 dst_y = flip_vertical ? (height - 1 - y) : y;
|
||||
u32* row_dst = pixels + (dst_y * width);
|
||||
u32 x = 0;
|
||||
|
||||
while (x < width)
|
||||
{
|
||||
// Check bounds before reading
|
||||
if (src_pos + 2 > src_size)
|
||||
return false;
|
||||
|
||||
const u8 count = src[src_pos++];
|
||||
const u8 value = src[src_pos++];
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (value == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (value == 2)
|
||||
{
|
||||
// Delta (jump) need 2 more bytes
|
||||
if (src_pos + 2 > src_size)
|
||||
return false;
|
||||
const u8 dx = src[src_pos++];
|
||||
const u8 dy = src[src_pos++];
|
||||
x += dx;
|
||||
y += dy;
|
||||
if (y >= height || x >= width)
|
||||
return false;
|
||||
const u32 new_dst_y = flip_vertical ? (height - 1 - y) : y;
|
||||
row_dst = pixels + (new_dst_y * width);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Absolute mode need "value" bytes of pixel data
|
||||
const u32 run_length = value;
|
||||
const u32 bytes_needed = run_length * pixel_size;
|
||||
if (src_pos + bytes_needed > src_size)
|
||||
return false;
|
||||
|
||||
for (u32 i = 0; i < run_length; i++)
|
||||
{
|
||||
if (x >= width)
|
||||
break;
|
||||
|
||||
u8 pixel_value = 0;
|
||||
if (info_header.bit_count == 8)
|
||||
{
|
||||
pixel_value = src[src_pos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8 byte_val = src[src_pos++];
|
||||
pixel_value = (i % 2 == 0) ? (byte_val >> 4) : (byte_val & 0x0F);
|
||||
}
|
||||
|
||||
row_dst[x++] = (pixel_value < palette.size()) ? palette[pixel_value] : 0;
|
||||
}
|
||||
|
||||
if ((run_length * pixel_size) % 2 == 1)
|
||||
src_pos++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 pixel_value = value;
|
||||
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
if (x >= width)
|
||||
break;
|
||||
row_dst[x++] = (pixel_value < palette.size()) ? palette[pixel_value] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMPBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
||||
{
|
||||
if (buffer_size < sizeof(BMPFileHeader) + sizeof(BMPInfoHeader))
|
||||
{
|
||||
Console.Error("BMP file too small");
|
||||
return false;
|
||||
}
|
||||
|
||||
const u8* data = static_cast<const u8*>(buffer);
|
||||
BMPFileHeader file_header;
|
||||
BMPInfoHeader info_header;
|
||||
|
||||
std::memcpy(&file_header, data, sizeof(BMPFileHeader));
|
||||
std::memcpy(&info_header, data + sizeof(BMPFileHeader), sizeof(BMPInfoHeader));
|
||||
|
||||
if (file_header.type != 0x4D42)
|
||||
{
|
||||
Console.Error("Invalid BMP signature");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for extended header versions (V4=108 bytes, V5=124 bytes)
|
||||
// We read as BITMAPINFOHEADER (40 bytes) regardless, since extended headers just add fields at the end
|
||||
if (info_header.size == 108)
|
||||
{
|
||||
Console.Warning("BITMAPV4HEADER detected, reading as BITMAPINFOHEADER");
|
||||
}
|
||||
else if (info_header.size == 124)
|
||||
{
|
||||
Console.Warning("BITMAPV5HEADER detected, reading as BITMAPINFOHEADER");
|
||||
}
|
||||
else if (info_header.size != 40)
|
||||
{
|
||||
Console.Warning("Unknown BMP header size: %u, attempting to read as BITMAPINFOHEADER", info_header.size);
|
||||
}
|
||||
|
||||
if (!IsSupportedBMPFormat(info_header.compression, info_header.bit_count))
|
||||
{
|
||||
Console.Error("Unsupported BMP format: compression=%u, bit_count=%u", info_header.compression, info_header.bit_count);
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 width = static_cast<u32>(std::abs(info_header.width));
|
||||
const u32 height = static_cast<u32>(std::abs(info_header.height));
|
||||
const bool flip_vertical = (info_header.height > 0);
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
Console.Error("Invalid BMP dimensions: %ux%u", width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width > 65536 || height > 65536)
|
||||
{
|
||||
Console.Error("BMP dimensions too large: %ux%u", width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.WriteLn("BMP: %ux%u, %u-bit, compression=%u", width, height, info_header.bit_count, info_header.compression);
|
||||
|
||||
// Read color masks from header or bitfields
|
||||
u32 red_mask = 0;
|
||||
u32 green_mask = 0;
|
||||
u32 blue_mask = 0;
|
||||
u32 alpha_mask = 0;
|
||||
const bool bitfields = (info_header.compression == 3 || info_header.compression == 4); // BMP_BITFIELDS or BMP_ALPHABITFIELDS
|
||||
const u8* header_start = data + sizeof(BMPFileHeader);
|
||||
const u32 header_base_offset = sizeof(BMPFileHeader) + 40; // Base header is 40 bytes
|
||||
|
||||
if (info_header.size >= 108) // BMP_WIN4 (108) or BMP_WIN5 (124)
|
||||
{
|
||||
// V4/V5 headers masks come right after the 40-byte base header
|
||||
// Masks are at offsets from header_start: red=40, green=44, blue=48, alpha=52
|
||||
if (buffer_size >= header_base_offset + 16) // Need space for 4 masks
|
||||
{
|
||||
red_mask = *reinterpret_cast<const u32*>(header_start + 40);
|
||||
green_mask = *reinterpret_cast<const u32*>(header_start + 44);
|
||||
blue_mask = *reinterpret_cast<const u32*>(header_start + 48);
|
||||
alpha_mask = *reinterpret_cast<const u32*>(header_start + 52);
|
||||
}
|
||||
}
|
||||
else if (bitfields && (info_header.bit_count == 16 || info_header.bit_count == 32))
|
||||
{
|
||||
const u32 bitfields_offset = sizeof(BMPFileHeader) + info_header.size;
|
||||
if (buffer_size >= bitfields_offset + 12) // Need space for at least r/g/b masks
|
||||
{
|
||||
red_mask = *reinterpret_cast<const u32*>(data + bitfields_offset);
|
||||
green_mask = *reinterpret_cast<const u32*>(data + bitfields_offset + 4);
|
||||
blue_mask = *reinterpret_cast<const u32*>(data + bitfields_offset + 8);
|
||||
if (info_header.compression == 4) // BMP_ALPHABITFIELDS
|
||||
{
|
||||
// Read alpha mask: r, g, b, a
|
||||
if (buffer_size >= bitfields_offset + 16)
|
||||
alpha_mask = *reinterpret_cast<const u32*>(data + bitfields_offset + 12);
|
||||
}
|
||||
// For BMP_BITFIELDS (3), alpha_mask stays 0
|
||||
}
|
||||
}
|
||||
|
||||
bool use_alpha = bitfields || (info_header.compression == 0 && info_header.bit_count == 32 && alpha_mask == 0xff000000);
|
||||
use_alpha = use_alpha && (alpha_mask != 0);
|
||||
|
||||
const u32 bytes_per_pixel = info_header.bit_count / 8;
|
||||
const u32 row_size = ((width * bytes_per_pixel + 3) / 4) * 4;
|
||||
|
||||
// For uncompressed BMPs, verify we have enough data
|
||||
// For RLE-compressed BMPs, size is variable so we check differently
|
||||
if (info_header.compression == 0)
|
||||
{
|
||||
if (file_header.offset + (row_size * height) > buffer_size)
|
||||
{
|
||||
Console.Error("BMP file data incomplete");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For RLE-compressed BMPs, check that we have at least the offset and some data
|
||||
// Use biSizeImage if available, otherwise just verify offset is valid
|
||||
if (file_header.offset >= buffer_size)
|
||||
{
|
||||
Console.Error("BMP file data incomplete");
|
||||
return false;
|
||||
}
|
||||
if (info_header.size_image > 0)
|
||||
{
|
||||
if (file_header.offset + info_header.size_image > buffer_size)
|
||||
{
|
||||
Console.Error("BMP file data incomplete");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u32> pixels;
|
||||
pixels.resize(width * height);
|
||||
|
||||
const u8* src = data + file_header.offset;
|
||||
const u32 src_size = buffer_size - file_header.offset;
|
||||
|
||||
std::vector<u32> palette;
|
||||
if (info_header.bit_count <= 8)
|
||||
{
|
||||
if (!LoadBMPPalette(palette, data, file_header.offset, info_header))
|
||||
{
|
||||
Console.Error("Failed to load BMP palette");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (info_header.compression == 0 || info_header.compression == 3 || info_header.compression == 4)
|
||||
{
|
||||
if (!LoadUncompressedBMP(pixels.data(), src, data, width, height, info_header, palette, flip_vertical, red_mask, green_mask, blue_mask, alpha_mask, use_alpha))
|
||||
{
|
||||
Console.Error("Failed to load uncompressed BMP data");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!LoadCompressedBMP(pixels.data(), src, src_size, width, height, info_header, palette, flip_vertical))
|
||||
{
|
||||
Console.Error("Failed to load compressed BMP data");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle alpha channel for 32-bit BMPs
|
||||
// Only use alpha if alpha_mask is explicitly set in header/bitfields
|
||||
if (info_header.bit_count == 32 && !use_alpha)
|
||||
{
|
||||
// Alpha mask not set or zero - set all pixels to fully opaque
|
||||
for (u32& pixel : pixels)
|
||||
pixel |= 0xFF000000u;
|
||||
}
|
||||
|
||||
image->SetPixels(width, height, std::move(pixels));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMPFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||
{
|
||||
std::optional<std::vector<u8>> data = FileSystem::ReadBinaryFile(fp);
|
||||
if (!data.has_value())
|
||||
return false;
|
||||
|
||||
return BMPBufferLoader(image, data->data(), data->size());
|
||||
}
|
||||
|
||||
bool BMPBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality)
|
||||
{
|
||||
const u32 width = image.GetWidth();
|
||||
const u32 height = image.GetHeight();
|
||||
|
||||
// Check dimensions
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
Console.Error("Invalid BMP dimensions: %ux%u", width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 row_size = ((width * 3 + 3) / 4) * 4;
|
||||
const u32 image_size = row_size * height;
|
||||
const u32 file_size = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader) + image_size;
|
||||
|
||||
buffer->resize(file_size);
|
||||
u8* data = buffer->data();
|
||||
|
||||
BMPFileHeader file_header = {};
|
||||
file_header.type = 0x4D42;
|
||||
file_header.size = file_size;
|
||||
file_header.reserved1 = 0;
|
||||
file_header.reserved2 = 0;
|
||||
file_header.offset = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader);
|
||||
std::memcpy(data, &file_header, sizeof(BMPFileHeader));
|
||||
|
||||
BMPInfoHeader info_header = {};
|
||||
info_header.size = sizeof(BMPInfoHeader);
|
||||
info_header.width = static_cast<s32>(width);
|
||||
info_header.height = static_cast<s32>(height);
|
||||
info_header.planes = 1;
|
||||
info_header.bit_count = 24;
|
||||
info_header.compression = 0;
|
||||
info_header.size_image = image_size;
|
||||
info_header.x_pels_per_meter = 0;
|
||||
info_header.y_pels_per_meter = 0;
|
||||
info_header.clr_used = 0;
|
||||
info_header.clr_important = 0;
|
||||
std::memcpy(data + sizeof(BMPFileHeader), &info_header, sizeof(BMPInfoHeader));
|
||||
|
||||
u8* pixel_data = data + file_header.offset;
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
const u32 src_y = height - 1 - y;
|
||||
const u32* row_src = image.GetRowPixels(src_y);
|
||||
u8* row_dst = pixel_data + (y * row_size);
|
||||
|
||||
for (u32 x = 0; x < width; x++)
|
||||
{
|
||||
const u32 rgba = row_src[x];
|
||||
row_dst[x * 3 + 0] = static_cast<u8>((rgba >> 16) & 0xFF);
|
||||
row_dst[x * 3 + 1] = static_cast<u8>((rgba >> 8) & 0xFF);
|
||||
row_dst[x * 3 + 2] = static_cast<u8>(rgba & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMPFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality)
|
||||
{
|
||||
std::vector<u8> buffer;
|
||||
if (!BMPBufferSaver(image, &buffer, quality))
|
||||
return false;
|
||||
|
||||
return (std::fwrite(buffer.data(), buffer.size(), 1, fp) == 1);
|
||||
}
|
||||
|
||||
@@ -106,6 +106,11 @@ namespace Common
|
||||
Reset();
|
||||
}
|
||||
|
||||
Timer::Timer(Value start_value)
|
||||
{
|
||||
m_tvStartValue = start_value;
|
||||
}
|
||||
|
||||
void Timer::Reset()
|
||||
{
|
||||
m_tvStartValue = GetCurrentValue();
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Common
|
||||
using Value = std::uint64_t;
|
||||
|
||||
Timer();
|
||||
Timer (Value start_value);
|
||||
|
||||
static Value GetCurrentValue();
|
||||
static double ConvertValueToSeconds(Value value);
|
||||
|
||||
@@ -100,54 +100,16 @@ void Common::SetMousePosition(int x, int y)
|
||||
SetCursorPos(x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
static HHOOK mouseHook = nullptr;
|
||||
static std::function<void(int, int)> fnMouseMoveCb;
|
||||
LRESULT CALLBACK Mousecb(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode >= 0 && wParam == WM_MOUSEMOVE)
|
||||
{
|
||||
MSLLHOOKSTRUCT* mouse = (MSLLHOOKSTRUCT*)lParam;
|
||||
fnMouseMoveCb(mouse->pt.x, mouse->pt.y);
|
||||
}
|
||||
return CallNextHookEx(mouseHook, nCode, wParam, lParam);
|
||||
}
|
||||
*/
|
||||
|
||||
// This (and the above) works, but is not recommended on Windows and is only here for consistency.
|
||||
// Defer to using raw input instead.
|
||||
bool Common::AttachMousePositionCb(std::function<void(int, int)> cb)
|
||||
{
|
||||
/*
|
||||
if (mouseHook)
|
||||
Common::DetachMousePositionCb();
|
||||
|
||||
fnMouseMoveCb = cb;
|
||||
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, Mousecb, GetModuleHandle(NULL), 0);
|
||||
if (!mouseHook)
|
||||
{
|
||||
Console.Warning("Failed to set mouse hook: %d", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
|
||||
static bool warned = false;
|
||||
if (!warned)
|
||||
{
|
||||
Console.Warning("Mouse hooks are enabled, and this isn't a release build! Using a debugger, or loading symbols, _will_ stall the hook and cause global mouse lag.");
|
||||
warned = true;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
// We use raw input messages which are handled by the windows message loop.
|
||||
// The alternative is to use a low-level mouse hook, but this passes Windows all mouse messages to PCSX2.
|
||||
// If PCSX2 hangs, or you attach a debugger, the mouse will stop working system-wide.
|
||||
return true;
|
||||
}
|
||||
|
||||
void Common::DetachMousePositionCb()
|
||||
{
|
||||
/*
|
||||
UnhookWindowsHookEx(mouseHook);
|
||||
mouseHook = nullptr;
|
||||
*/
|
||||
}
|
||||
|
||||
bool Common::PlaySoundAsync(const char* path)
|
||||
|
||||
43
common/YAML.cpp
Normal file
43
common/YAML.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "YAML.h"
|
||||
|
||||
#include <csetjmp>
|
||||
#include <cstdlib>
|
||||
|
||||
struct RapidYAMLContext
|
||||
{
|
||||
std::jmp_buf env;
|
||||
Error* error = nullptr;
|
||||
};
|
||||
|
||||
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error)
|
||||
{
|
||||
RapidYAMLContext context;
|
||||
context.error = error;
|
||||
|
||||
ryml::Callbacks callbacks;
|
||||
callbacks.m_user_data = static_cast<void*>(&context);
|
||||
callbacks.m_error = [](const char* msg, size_t msg_len, ryml::Location location, void* user_data) {
|
||||
RapidYAMLContext* context = static_cast<RapidYAMLContext*>(user_data);
|
||||
|
||||
Error::SetString(context->error, std::string(msg, msg_len));
|
||||
std::longjmp(context->env, 1);
|
||||
};
|
||||
|
||||
ryml::EventHandlerTree event_handler(callbacks);
|
||||
ryml::Parser parser(&event_handler);
|
||||
|
||||
ryml::Tree tree;
|
||||
|
||||
// The only options RapidYAML provides for recovering from errors are
|
||||
// throwing an exception or using setjmp/longjmp. Since we have exceptions
|
||||
// disabled we have to use the latter option.
|
||||
if (setjmp(context.env))
|
||||
return std::nullopt;
|
||||
|
||||
ryml::parse_in_arena(&parser, file_name, yaml, &tree);
|
||||
|
||||
return tree;
|
||||
}
|
||||
18
common/YAML.h
Normal file
18
common/YAML.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Error.h"
|
||||
|
||||
#include "ryml_std.hpp"
|
||||
#include "ryml.hpp"
|
||||
#include "ryml.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
/// Parse a YAML file with RapidYAML, and use setjmp/longjmp to recover from
|
||||
/// parsing errors (as is recommended by the documentation for cases where
|
||||
/// exceptions are disabled). The file_name parameter is only used for error
|
||||
/// messages, which are returned via the error parameter.
|
||||
std::optional<ryml::Tree> ParseYAMLFromString(ryml::csubstr yaml, ryml::csubstr file_name, Error* error);
|
||||
@@ -36,10 +36,12 @@
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fast_float\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fmt\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\jpgd</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\rapidyaml\include</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<ForcedIncludeFiles>PrecompiledHeader.h</ForcedIncludeFiles>
|
||||
<PrecompiledHeaderFile>PrecompiledHeader.h</PrecompiledHeaderFile>
|
||||
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
|
||||
<PreprocessorDefinitions>C4_NO_DEBUG_BREAK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
@@ -71,6 +73,7 @@
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="WAVWriter.cpp" />
|
||||
<ClCompile Include="WindowInfo.cpp" />
|
||||
<ClCompile Include="YAML.cpp" />
|
||||
<ClCompile Include="Perf.cpp" />
|
||||
<ClCompile Include="PrecompiledHeader.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
@@ -157,6 +160,7 @@
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="WAVWriter.h" />
|
||||
<ClInclude Include="WindowInfo.h" />
|
||||
<ClInclude Include="YAML.h" />
|
||||
<ClInclude Include="Threading.h" />
|
||||
<ClInclude Include="emitter\implement\avx.h" />
|
||||
<ClInclude Include="emitter\implement\bmi.h" />
|
||||
|
||||
@@ -127,6 +127,9 @@
|
||||
<ClCompile Include="SmallString.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YAML.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AlignedMalloc.h">
|
||||
@@ -335,6 +338,9 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="SingleRegisterTypes.h" />
|
||||
<ClInclude Include="FPControl.h" />
|
||||
<ClInclude Include="YAML.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
@@ -349,4 +355,4 @@
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace GSRunner
|
||||
{
|
||||
static void InitializeConsole();
|
||||
static bool InitializeConfig();
|
||||
static void SettingsOverride();
|
||||
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
|
||||
static void DumpStats();
|
||||
|
||||
@@ -119,42 +120,6 @@ bool GSRunner::InitializeConfig()
|
||||
|
||||
VMManager::SetDefaultSettings(si, true, true, true, true, true);
|
||||
|
||||
// complete as quickly as possible
|
||||
si.SetBoolValue("EmuCore/GS", "FrameLimitEnable", false);
|
||||
si.SetIntValue("EmuCore/GS", "VsyncEnable", false);
|
||||
|
||||
// Force screenshot quality settings to something more performant, overriding any defaults good for users.
|
||||
si.SetIntValue("EmuCore/GS", "ScreenshotFormat", static_cast<int>(GSScreenshotFormat::PNG));
|
||||
si.SetIntValue("EmuCore/GS", "ScreenshotQuality", 10);
|
||||
|
||||
// ensure all input sources are disabled, we're not using them
|
||||
si.SetBoolValue("InputSources", "SDL", false);
|
||||
si.SetBoolValue("InputSources", "XInput", false);
|
||||
|
||||
// we don't need any sound output
|
||||
si.SetStringValue("SPU2/Output", "OutputModule", "nullout");
|
||||
|
||||
// none of the bindings are going to resolve to anything
|
||||
Pad::ClearPortBindings(si, 0);
|
||||
si.ClearSection("Hotkeys");
|
||||
|
||||
// force logging
|
||||
si.SetBoolValue("Logging", "EnableSystemConsole", !s_no_console);
|
||||
si.SetBoolValue("Logging", "EnableTimestamps", true);
|
||||
si.SetBoolValue("Logging", "EnableVerbose", true);
|
||||
|
||||
// and show some stats :)
|
||||
si.SetBoolValue("EmuCore/GS", "OsdShowFPS", true);
|
||||
si.SetBoolValue("EmuCore/GS", "OsdShowResolution", true);
|
||||
si.SetBoolValue("EmuCore/GS", "OsdShowGSStats", true);
|
||||
|
||||
// remove memory cards, so we don't have sharing violations
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
{
|
||||
si.SetBoolValue("MemoryCards", fmt::format("Slot{}_Enable", i + 1).c_str(), false);
|
||||
si.SetStringValue("MemoryCards", fmt::format("Slot{}_Filename", i + 1).c_str(), "");
|
||||
}
|
||||
|
||||
VMManager::Internal::LoadStartupSettings();
|
||||
return true;
|
||||
}
|
||||
@@ -481,8 +446,8 @@ static void PrintCommandLineHelp(const char* progname)
|
||||
std::fprintf(stderr, " -help: Displays this information and exits.\n");
|
||||
std::fprintf(stderr, " -version: Displays version information and exits.\n");
|
||||
std::fprintf(stderr, " -dumpdir <dir>: Frame dump directory (will be dumped as filename_frameN.png).\n");
|
||||
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr]: Enabling dumping of render target, texture, z buffer, frame, "
|
||||
"alphas, and info (context, vertices, transfers (list)), transfers (images), respectively, per draw. Generates lots of data.\n");
|
||||
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr|ds|fs]: Enabling dumping of render target, texture, z buffer, frame, "
|
||||
"alphas, and info (context, vertices, list of transfers), transfers images, draw stats, frame stats, respectively, per draw. Generates lots of data.\n");
|
||||
std::fprintf(stderr, " -dumprange N[,L,B]: Start dumping from draw N (base 0), stops after L draws, and only "
|
||||
"those draws that are multiples of B (intersection of -dumprange and -dumprangef used)."
|
||||
"Defaults to 0,-1,1 (all draws). Only used if -dump used.\n");
|
||||
@@ -568,6 +533,10 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveInfo", true);
|
||||
if (str.find("tr") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveTransferImages", true);
|
||||
if (str.find("ds") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveDrawStats", true);
|
||||
if (str.find("fs") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveFrameStats", true);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-dumprange"))
|
||||
@@ -709,6 +678,28 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-ini"))
|
||||
{
|
||||
std::string path = std::string(StringUtil::StripWhitespace(argv[++i]));
|
||||
if (!FileSystem::FileExists(path.c_str()))
|
||||
{
|
||||
Console.ErrorFmt("INI file {} does not exit.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
INISettingsInterface si_ini(path);
|
||||
|
||||
if (!si_ini.Load())
|
||||
{
|
||||
Console.ErrorFmt("Unable to load INI settings from {}.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& [key, value] : si_ini.GetKeyValueList("EmuCore/GS"))
|
||||
s_settings_interface.SetStringValue("EmuCore/GS", key.c_str(), value.c_str());
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-upscale"))
|
||||
{
|
||||
const float upscale = StringUtil::FromChars<float>(argv[++i]).value_or(0.0f);
|
||||
@@ -739,7 +730,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
else if (CHECK_ARG("-noshadercache"))
|
||||
{
|
||||
Console.WriteLn("Disabling shader cache");
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "disable_shader_cache", true);
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "DisableShaderCache", true);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG("-window"))
|
||||
@@ -813,6 +804,45 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSRunner::SettingsOverride()
|
||||
{
|
||||
// complete as quickly as possible
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "FrameLimitEnable", false);
|
||||
s_settings_interface.SetIntValue("EmuCore/GS", "VsyncEnable", false);
|
||||
|
||||
// Force screenshot quality settings to something more performant, overriding any defaults good for users.
|
||||
s_settings_interface.SetIntValue("EmuCore/GS", "ScreenshotFormat", static_cast<int>(GSScreenshotFormat::PNG));
|
||||
s_settings_interface.SetIntValue("EmuCore/GS", "ScreenshotQuality", 10);
|
||||
|
||||
// ensure all input sources are disabled, we're not using them
|
||||
s_settings_interface.SetBoolValue("InputSources", "SDL", false);
|
||||
s_settings_interface.SetBoolValue("InputSources", "XInput", false);
|
||||
|
||||
// we don't need any sound output
|
||||
s_settings_interface.SetStringValue("SPU2/Output", "OutputModule", "nullout");
|
||||
|
||||
// none of the bindings are going to resolve to anything
|
||||
Pad::ClearPortBindings(s_settings_interface, 0);
|
||||
s_settings_interface.ClearSection("Hotkeys");
|
||||
|
||||
// force logging
|
||||
s_settings_interface.SetBoolValue("Logging", "EnableSystemConsole", !s_no_console);
|
||||
s_settings_interface.SetBoolValue("Logging", "EnableTimestamps", true);
|
||||
s_settings_interface.SetBoolValue("Logging", "EnableVerbose", true);
|
||||
|
||||
// and show some stats :)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "OsdShowFPS", true);
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "OsdShowResolution", true);
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "OsdShowGSStats", true);
|
||||
|
||||
// remove memory cards, so we don't have sharing violations
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
{
|
||||
s_settings_interface.SetBoolValue("MemoryCards", fmt::format("Slot{}_Enable", i + 1).c_str(), false);
|
||||
s_settings_interface.SetStringValue("MemoryCards", fmt::format("Slot{}_Filename", i + 1).c_str(), "");
|
||||
}
|
||||
}
|
||||
|
||||
void GSRunner::DumpStats()
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
@@ -831,16 +861,27 @@ void GSRunner::DumpStats()
|
||||
#define main real_main
|
||||
#endif
|
||||
|
||||
static void CPUThreadMain(VMBootParameters* params) {
|
||||
if (VMManager::Initialize(*params))
|
||||
static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
|
||||
{
|
||||
ret->store(EXIT_FAILURE);
|
||||
|
||||
if (VMManager::Internal::CPUThreadInitialize())
|
||||
{
|
||||
// run until end
|
||||
GSDumpReplayer::SetLoopCount(s_loop_count);
|
||||
VMManager::SetState(VMState::Running);
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
// apply new settings (e.g. pick up renderer change)
|
||||
VMManager::ApplySettings();
|
||||
GSDumpReplayer::SetIsDumpRunner(true);
|
||||
|
||||
if (VMManager::Initialize(*params))
|
||||
{
|
||||
// run until end
|
||||
GSDumpReplayer::SetLoopCount(s_loop_count);
|
||||
VMManager::SetState(VMState::Running);
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
ret->store(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
VMManager::Internal::CPUThreadShutdown();
|
||||
@@ -862,27 +903,23 @@ int main(int argc, char* argv[])
|
||||
if (!GSRunner::ParseCommandLineArgs(argc, argv, params))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!VMManager::Internal::CPUThreadInitialize())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (s_use_window.value_or(true) && !GSRunner::CreatePlatformWindow())
|
||||
{
|
||||
Console.Error("Failed to create window.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// apply new settings (e.g. pick up renderer change)
|
||||
VMManager::ApplySettings();
|
||||
GSDumpReplayer::SetIsDumpRunner(true);
|
||||
// Override settings that shouldn't be picked up from defaults or INIs.
|
||||
GSRunner::SettingsOverride();
|
||||
|
||||
std::thread cputhread(CPUThreadMain, ¶ms);
|
||||
std::atomic<int> thread_ret;
|
||||
std::thread cputhread(CPUThreadMain, ¶ms, &thread_ret);
|
||||
GSRunner::PumpPlatformMessages(/*forever=*/true);
|
||||
cputhread.join();
|
||||
|
||||
VMManager::Internal::CPUThreadShutdown();
|
||||
GSRunner::DestroyPlatformWindow();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return thread_ret.load();
|
||||
}
|
||||
|
||||
void Host::PumpMessagesOnCPUThread()
|
||||
|
||||
@@ -81,6 +81,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -115,6 +118,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<class>AutoUpdaterDialog</class>
|
||||
<widget class="QDialog" name="AutoUpdaterDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -91,7 +91,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -132,6 +132,12 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>updateNotes</tabstop>
|
||||
<tabstop>downloadAndInstall</tabstop>
|
||||
<tabstop>skipThisUpdate</tabstop>
|
||||
<tabstop>remindMeLater</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -264,6 +264,14 @@ target_sources(pcsx2-qt PRIVATE
|
||||
resources/resources.qrc
|
||||
)
|
||||
|
||||
if (NOT APPLE)
|
||||
target_sources(pcsx2-qt PRIVATE
|
||||
ShortcutCreationDialog.cpp
|
||||
ShortcutCreationDialog.h
|
||||
ShortcutCreationDialog.ui
|
||||
)
|
||||
endif()
|
||||
|
||||
file(GLOB TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Translations/*.ts)
|
||||
|
||||
target_precompile_headers(pcsx2-qt PRIVATE PrecompiledHeader.h)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<pixmap resource="resources/resources.qrc">:/icons/black/svg/artboard-2-line.svg</pixmap>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -40,6 +40,12 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>label</cstring>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -52,6 +58,12 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>urls</cstring>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -65,6 +77,12 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>useTitleFileNames</cstring>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -110,6 +128,12 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>urls</tabstop>
|
||||
<tabstop>useTitleFileNames</tabstop>
|
||||
<tabstop>start</tabstop>
|
||||
<tabstop>close</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -45,10 +48,10 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
@@ -80,7 +83,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -108,6 +111,12 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>closeCheckBox</tabstop>
|
||||
<tabstop>analyseButton</tabstop>
|
||||
<tabstop>closeButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<class>BreakpointDialog</class>
|
||||
<widget class="QDialog" name="BreakpointDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -56,10 +56,10 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="grpType">
|
||||
@@ -111,13 +111,16 @@
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtAddress</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -147,6 +150,9 @@
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtDescription</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -221,6 +227,9 @@
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtSize</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -264,6 +273,9 @@
|
||||
<property name="text">
|
||||
<string>Condition</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtCondition</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -310,6 +322,19 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>rdoMemory</tabstop>
|
||||
<tabstop>rdoExecute</tabstop>
|
||||
<tabstop>txtAddress</tabstop>
|
||||
<tabstop>txtDescription</tabstop>
|
||||
<tabstop>chkLog</tabstop>
|
||||
<tabstop>chkEnable</tabstop>
|
||||
<tabstop>chkRead</tabstop>
|
||||
<tabstop>chkWrite</tabstop>
|
||||
<tabstop>chkChange</tabstop>
|
||||
<tabstop>txtSize</tabstop>
|
||||
<tabstop>txtCondition</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
||||
@@ -153,7 +153,7 @@ void DebuggerSettingsManager::saveGameSettings(QAbstractTableModel* abstractTabl
|
||||
if (path.empty())
|
||||
return;
|
||||
|
||||
const std::lock_guard<std::mutex> lock(writeLock);
|
||||
std::lock_guard<std::mutex> lock(writeLock);
|
||||
QJsonObject loadedSettings = loadGameSettingsJSON();
|
||||
QJsonArray rowsArray;
|
||||
QStringList keys;
|
||||
|
||||
@@ -238,6 +238,12 @@ int DebuggerWindow::fontSize()
|
||||
|
||||
void DebuggerWindow::updateTheme()
|
||||
{
|
||||
// Detect recursive StyleChange events caused by updating the stylesheet.
|
||||
if (m_is_updating_theme)
|
||||
return;
|
||||
|
||||
m_is_updating_theme = true;
|
||||
|
||||
// TODO: Migrate away from stylesheets to improve performance.
|
||||
setStyleSheet(QString("font-size: %1pt;").arg(m_font_size));
|
||||
|
||||
@@ -248,6 +254,8 @@ void DebuggerWindow::updateTheme()
|
||||
setStyleSheet(QString());
|
||||
|
||||
dockManager().updateTheme();
|
||||
|
||||
m_is_updating_theme = false;
|
||||
}
|
||||
|
||||
void DebuggerWindow::saveWindowGeometry()
|
||||
@@ -535,6 +543,12 @@ void DebuggerWindow::onStepOut()
|
||||
this->repaint();
|
||||
}
|
||||
|
||||
void DebuggerWindow::changeEvent(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::PaletteChange || event->type() == QEvent::StyleChange)
|
||||
updateTheme();
|
||||
}
|
||||
|
||||
void DebuggerWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
dockManager().saveCurrentLayout();
|
||||
|
||||
@@ -60,7 +60,8 @@ Q_SIGNALS:
|
||||
void onVMActuallyPaused();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event);
|
||||
void changeEvent(QEvent* event) override;
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
private:
|
||||
DebugInterface* currentCPU();
|
||||
@@ -75,6 +76,8 @@ private:
|
||||
int m_font_size;
|
||||
static const constexpr int MINIMUM_FONT_SIZE = 5;
|
||||
static const constexpr int MAXIMUM_FONT_SIZE = 30;
|
||||
|
||||
bool m_is_updating_theme = false;
|
||||
};
|
||||
|
||||
extern DebuggerWindow* g_debugger_window;
|
||||
|
||||
@@ -424,7 +424,7 @@ void DisassemblyView::paintEvent(QPaintEvent* event)
|
||||
bool alternate = m_visibleStart % 8;
|
||||
|
||||
// Draw visible disassembly rows
|
||||
for (u32 i = 0; i <= m_visibleRows; i++)
|
||||
for (u32 i = 0; i < m_visibleRows + 1; i++)
|
||||
{
|
||||
// Address of instruction being displayed on row
|
||||
const u32 rowAddress = (i * 4) + m_visibleStart;
|
||||
@@ -939,7 +939,7 @@ inline QString DisassemblyView::DisassemblyStringFromAddress(u32 address, QFont
|
||||
QColor DisassemblyView::GetAddressFunctionColor(u32 address)
|
||||
{
|
||||
std::array<QColor, 6> colors;
|
||||
if (QtUtils::IsLightTheme(palette()))
|
||||
if (!QtHost::IsDarkApplicationTheme())
|
||||
{
|
||||
colors = {
|
||||
QColor::fromRgba(0xFFFA3434),
|
||||
@@ -977,18 +977,18 @@ QColor DisassemblyView::GetAddressFunctionColor(u32 address)
|
||||
QString DisassemblyView::FetchSelectionInfo(SelectionInfo selInfo)
|
||||
{
|
||||
QString infoBlock;
|
||||
for (u32 i = m_selectedAddressStart; i <= m_selectedAddressEnd; i += 4)
|
||||
for (u64 i = m_selectedAddressStart; i <= m_selectedAddressEnd; i += 4)
|
||||
{
|
||||
if (i != m_selectedAddressStart)
|
||||
infoBlock += '\n';
|
||||
if (selInfo == SelectionInfo::ADDRESS)
|
||||
{
|
||||
infoBlock += FilledQStringFromValue(i, 16);
|
||||
infoBlock += FilledQStringFromValue(static_cast<u32>(i), 16);
|
||||
}
|
||||
else if (selInfo == SelectionInfo::INSTRUCTIONTEXT)
|
||||
{
|
||||
DisassemblyLineInfo line;
|
||||
m_disassemblyManager.getLine(i, true, line);
|
||||
m_disassemblyManager.getLine(static_cast<u32>(i), true, line);
|
||||
infoBlock += QString("%1 %2").arg(line.name.c_str()).arg(line.params.c_str());
|
||||
}
|
||||
else // INSTRUCTIONHEX
|
||||
@@ -1075,9 +1075,9 @@ void DisassemblyView::setInstructions(u32 start, u32 end, u32 value)
|
||||
|
||||
bool DisassemblyView::AddressCanRestore(u32 start, u32 end)
|
||||
{
|
||||
for (u32 i = start; i <= end; i += 4)
|
||||
for (u64 i = start; i <= end; i += 4)
|
||||
{
|
||||
if (this->m_nopedInstructions.find(i) != this->m_nopedInstructions.end())
|
||||
if (this->m_nopedInstructions.find(static_cast<u32>(i)) != this->m_nopedInstructions.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,39 +6,36 @@
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPaintEvent>
|
||||
#include <QtWidgets/QBoxLayout>
|
||||
#include <QtWidgets/QStyleFactory>
|
||||
#include <QtWidgets/QStyleOption>
|
||||
|
||||
static const int OUTER_MENU_MARGIN = 2;
|
||||
static const int INNER_MENU_MARGIN = 4;
|
||||
static constexpr int TAB_BAR_TOP_MARGIN = 2;
|
||||
static constexpr int RIGHT_MARGIN = 2;
|
||||
|
||||
DockMenuBar::DockMenuBar(QWidget* original_menu_bar, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_original_menu_bar(original_menu_bar)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout;
|
||||
layout->setContentsMargins(0, OUTER_MENU_MARGIN, OUTER_MENU_MARGIN, 0);
|
||||
setLayout(layout);
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, RIGHT_MARGIN, 0);
|
||||
|
||||
QWidget* menu_wrapper = new QWidget;
|
||||
menu_wrapper->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
layout->addWidget(menu_wrapper);
|
||||
QWidget* menu_bar_wrapper = new QWidget;
|
||||
layout->addWidget(menu_bar_wrapper);
|
||||
|
||||
QHBoxLayout* menu_layout = new QHBoxLayout;
|
||||
menu_layout->setContentsMargins(0, INNER_MENU_MARGIN, 0, INNER_MENU_MARGIN);
|
||||
menu_wrapper->setLayout(menu_layout);
|
||||
QVBoxLayout* menu_bar_layout = new QVBoxLayout(menu_bar_wrapper);
|
||||
menu_bar_layout->setContentsMargins(0, 0, 0, 0);
|
||||
menu_bar_layout->addWidget(original_menu_bar, 0, Qt::AlignVCenter);
|
||||
|
||||
menu_layout->addWidget(original_menu_bar);
|
||||
QWidget* layout_switcher_wrapper = new QWidget;
|
||||
layout->addWidget(layout_switcher_wrapper);
|
||||
|
||||
m_layout_switcher_layout = new QVBoxLayout(layout_switcher_wrapper);
|
||||
|
||||
m_layout_switcher = new QTabBar;
|
||||
m_layout_switcher->setContentsMargins(0, 0, 0, 0);
|
||||
m_layout_switcher->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
m_layout_switcher->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_layout_switcher->setDrawBase(false);
|
||||
m_layout_switcher->setExpanding(false);
|
||||
m_layout_switcher->setMovable(true);
|
||||
layout->addWidget(m_layout_switcher);
|
||||
|
||||
connect(m_layout_switcher, &QTabBar::tabMoved, this, [this](int from, int to) {
|
||||
DockLayout::Index from_index = static_cast<DockLayout::Index>(from);
|
||||
@@ -63,6 +60,10 @@ DockMenuBar::DockMenuBar(QWidget* original_menu_bar, QWidget* parent)
|
||||
});
|
||||
layout->addWidget(m_layout_locked_toggle);
|
||||
|
||||
layout->setStretchFactor(menu_bar_wrapper, 0);
|
||||
layout->setStretchFactor(layout_switcher_wrapper, 1);
|
||||
layout->setStretchFactor(m_layout_locked_toggle, 0);
|
||||
|
||||
updateTheme();
|
||||
}
|
||||
|
||||
@@ -75,6 +76,19 @@ void DockMenuBar::updateTheme()
|
||||
|
||||
delete m_style;
|
||||
m_style = style;
|
||||
|
||||
// Vertically centre the layout switcher tabs for the Windows 11 style
|
||||
// because I think it looks better. Do the same for macOS too.
|
||||
if (style->baseStyle()->name() == "windows11" || style->baseStyle()->name() == "macOS")
|
||||
{
|
||||
m_layout_switcher_layout->setContentsMargins(0, 0, 0, 0);
|
||||
m_layout_switcher_layout->addWidget(m_layout_switcher, 0, Qt::AlignVCenter);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layout_switcher_layout->setContentsMargins(0, TAB_BAR_TOP_MARGIN, 0, 0);
|
||||
m_layout_switcher_layout->addWidget(m_layout_switcher, 0, Qt::AlignBottom);
|
||||
}
|
||||
}
|
||||
|
||||
void DockMenuBar::updateLayoutSwitcher(DockLayout::Index current_index, const std::vector<DockLayout>& layouts)
|
||||
@@ -182,11 +196,6 @@ void DockMenuBar::stopBlink()
|
||||
}
|
||||
}
|
||||
|
||||
int DockMenuBar::innerHeight() const
|
||||
{
|
||||
return m_original_menu_bar->sizeHint().height() + INNER_MENU_MARGIN * 2;
|
||||
}
|
||||
|
||||
void DockMenuBar::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
@@ -236,39 +245,6 @@ void DockMenuBarStyle::drawControl(
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
case CE_MenuBarItem:
|
||||
{
|
||||
const QStyleOptionMenuItem* opt = qstyleoption_cast<const QStyleOptionMenuItem*>(option);
|
||||
if (!opt)
|
||||
break;
|
||||
|
||||
QWidget* menu_wrapper = widget->parentWidget();
|
||||
if (!menu_wrapper)
|
||||
break;
|
||||
|
||||
const DockMenuBar* menu_bar = qobject_cast<const DockMenuBar*>(menu_wrapper->parentWidget());
|
||||
if (!menu_bar)
|
||||
break;
|
||||
|
||||
if (baseStyle()->name() != "fusion")
|
||||
break;
|
||||
|
||||
// This mirrors a check in QFusionStyle::drawControl. If act is
|
||||
// false, QFusionStyle will try to draw a border along the bottom.
|
||||
bool act = opt->state & State_Selected && opt->state & State_Sunken;
|
||||
if (act)
|
||||
break;
|
||||
|
||||
// Extend the menu item to the bottom of the menu bar to fix the
|
||||
// position in which it draws its bottom border. We also need to
|
||||
// extend it up by the same amount so that the text isn't moved.
|
||||
QStyleOptionMenuItem menu_opt = *opt;
|
||||
int difference = (menu_bar->innerHeight() - option->rect.top()) - menu_opt.rect.height();
|
||||
menu_opt.rect.adjust(0, -difference, 0, difference);
|
||||
QProxyStyle::drawControl(element, &menu_opt, painter, widget);
|
||||
|
||||
return;
|
||||
}
|
||||
case CE_TabBarTab:
|
||||
{
|
||||
QProxyStyle::drawControl(element, option, painter, widget);
|
||||
@@ -286,6 +262,25 @@ void DockMenuBarStyle::drawControl(
|
||||
|
||||
return;
|
||||
}
|
||||
case CE_MenuBarItem:
|
||||
{
|
||||
const QStyleOptionMenuItem* opt = qstyleoption_cast<const QStyleOptionMenuItem*>(option);
|
||||
if (!opt)
|
||||
break;
|
||||
|
||||
if (baseStyle()->name() != "fusion")
|
||||
break;
|
||||
|
||||
// This mirrors a check in QFusionStyle::drawControl. If act is
|
||||
// false, QFusionStyle will try to draw a border along the bottom.
|
||||
bool act = opt->state & State_Selected && opt->state & State_Sunken;
|
||||
if (act)
|
||||
break;
|
||||
|
||||
QCommonStyle::drawControl(element, option, painter, widget);
|
||||
|
||||
return;
|
||||
}
|
||||
case CE_MenuBarEmptyArea:
|
||||
{
|
||||
// Prevent it from drawing a border in the wrong position.
|
||||
@@ -301,11 +296,13 @@ void DockMenuBarStyle::drawControl(
|
||||
}
|
||||
|
||||
QSize DockMenuBarStyle::sizeFromContents(
|
||||
QStyle::ContentsType type, const QStyleOption* option, const QSize& contents_size, const QWidget* widget) const
|
||||
QStyle::ContentsType type,
|
||||
const QStyleOption* option,
|
||||
const QSize& contents_size,
|
||||
const QWidget* widget) const
|
||||
{
|
||||
QSize size = QProxyStyle::sizeFromContents(type, option, contents_size, widget);
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
// Adjust the sizes of the layout switcher tabs depending on the theme.
|
||||
if (type == CT_TabBarTab)
|
||||
{
|
||||
@@ -313,30 +310,12 @@ QSize DockMenuBarStyle::sizeFromContents(
|
||||
if (!opt)
|
||||
return size;
|
||||
|
||||
const QTabBar* tab_bar = qobject_cast<const QTabBar*>(widget);
|
||||
if (!tab_bar)
|
||||
return size;
|
||||
|
||||
const DockMenuBar* menu_bar = qobject_cast<const DockMenuBar*>(tab_bar->parentWidget());
|
||||
if (!menu_bar)
|
||||
return size;
|
||||
|
||||
if (baseStyle()->name() == "fusion" || baseStyle()->name() == "windowsvista")
|
||||
if (baseStyle()->name() == "windows11")
|
||||
{
|
||||
// Make sure the tab extends to the bottom of the widget.
|
||||
size.setHeight(menu_bar->innerHeight() - opt->rect.top());
|
||||
}
|
||||
else if (baseStyle()->name() == "windows11")
|
||||
{
|
||||
// Adjust the size of the tab such that it is vertically centred.
|
||||
size.setHeight(menu_bar->innerHeight() - opt->rect.top() * 2 - OUTER_MENU_MARGIN);
|
||||
|
||||
// Make the plus button square.
|
||||
if (opt->tabIndex + 1 == tab_bar->count())
|
||||
size.setWidth(size.height());
|
||||
// Make the tabs a bit taller, otherwise there's an awkward margin.
|
||||
size.setHeight(size.height() + 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QtWidgets/QProxyStyle>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QTabBar>
|
||||
#include <QtWidgets/QBoxLayout>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class DockMenuBarStyle;
|
||||
@@ -36,8 +37,6 @@ public:
|
||||
void updateBlink();
|
||||
void stopBlink();
|
||||
|
||||
int innerHeight() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentLayoutChanged(DockLayout::Index layout_index);
|
||||
void newButtonClicked();
|
||||
@@ -54,6 +53,7 @@ private:
|
||||
|
||||
QWidget* m_original_menu_bar;
|
||||
|
||||
QVBoxLayout* m_layout_switcher_layout;
|
||||
QTabBar* m_layout_switcher;
|
||||
QMetaObject::Connection m_tab_connection;
|
||||
int m_plus_tab_index = -1;
|
||||
@@ -70,8 +70,7 @@ private:
|
||||
DockMenuBarStyle* m_style = nullptr;
|
||||
};
|
||||
|
||||
// Fixes some theming issues relating to the menu bar, the layout switcher and
|
||||
// the layout locked/unlocked toggle button.
|
||||
// Fixes some theming issues relating to the menu bar and the layout switcher.
|
||||
class DockMenuBarStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -83,11 +82,11 @@ public:
|
||||
ControlElement element,
|
||||
const QStyleOption* option,
|
||||
QPainter* painter,
|
||||
const QWidget* widget = nullptr) const override;
|
||||
const QWidget* widget) const override;
|
||||
|
||||
QSize sizeFromContents(
|
||||
QStyle::ContentsType type,
|
||||
const QStyleOption* option,
|
||||
const QSize& contents_size,
|
||||
const QWidget* widget = nullptr) const override;
|
||||
const QWidget* widget) const override;
|
||||
};
|
||||
|
||||
@@ -145,15 +145,8 @@ DockTabBar::DockTabBar(KDDockWidgets::Core::TabBar* controller, QWidget* parent)
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, &DockTabBar::customContextMenuRequested, this, &DockTabBar::openContextMenu);
|
||||
|
||||
// The constructor of KDDockWidgets::QtWidgets::TabBar makes a QProxyStyle
|
||||
// that ends up taking ownerhsip of the style for the entire application!
|
||||
if (QProxyStyle* proxy_style = qobject_cast<QProxyStyle*>(style()))
|
||||
{
|
||||
if (proxy_style->baseStyle() == qApp->style())
|
||||
proxy_style->baseStyle()->setParent(qApp);
|
||||
|
||||
proxy_style->setBaseStyle(QStyleFactory::create(qApp->style()->name()));
|
||||
}
|
||||
}
|
||||
|
||||
void DockTabBar::openContextMenu(QPoint pos)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "DropIndicators.h"
|
||||
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "Debugger/Docking/DockViews.h"
|
||||
|
||||
@@ -21,7 +22,7 @@ static std::pair<QColor, QColor> pickNiceColours(const QPalette& palette, bool h
|
||||
QColor fill = palette.highlight().color();
|
||||
QColor outline = palette.highlight().color();
|
||||
|
||||
if (QtUtils::IsLightTheme(palette))
|
||||
if (!QtHost::IsDarkApplicationTheme())
|
||||
{
|
||||
fill = fill.darker(200);
|
||||
outline = outline.darker(200);
|
||||
@@ -197,7 +198,7 @@ static const constexpr int INDICATOR_MARGIN = 10;
|
||||
static bool isWayland()
|
||||
{
|
||||
return KDDockWidgets::Core::Platform::instance()->displayType() ==
|
||||
KDDockWidgets::Core::Platform::DisplayType::Wayland;
|
||||
KDDockWidgets::Core::Platform::DisplayType::Wayland;
|
||||
}
|
||||
|
||||
static QWidget* parentForIndicatorWindow(KDDockWidgets::Core::ClassicDropIndicatorOverlay* classic_indicators)
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>nameEditor</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
@@ -28,6 +31,9 @@
|
||||
<property name="text">
|
||||
<string>Target</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>cpuEditor</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@@ -35,6 +41,9 @@
|
||||
<property name="text">
|
||||
<string>Initial State</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>initialStateEditor</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -66,10 +75,10 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -77,6 +86,11 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>nameEditor</tabstop>
|
||||
<tabstop>cpuEditor</tabstop>
|
||||
<tabstop>initialStateEditor</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<item>
|
||||
<spacer name="topSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -36,7 +36,10 @@
|
||||
<string>There are no layouts.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>createDefaultLayoutsButton</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -45,7 +48,7 @@
|
||||
<item>
|
||||
<spacer name="leftSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -65,7 +68,7 @@
|
||||
<item>
|
||||
<spacer name="rightSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -80,7 +83,7 @@
|
||||
<item>
|
||||
<spacer name="bottomSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -92,6 +95,9 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>createDefaultLayoutsButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtSearchValue</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -31,6 +34,9 @@
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>cmbSearchType</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -82,6 +88,9 @@
|
||||
<property name="text">
|
||||
<string>Hex</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>chkSearchHex</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
@@ -155,20 +164,26 @@
|
||||
<property name="text">
|
||||
<string>Comparison</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>cmbSearchComparison</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" alignment="Qt::AlignLeft">
|
||||
<item row="0" column="0" alignment="Qt::AlignmentFlag::AlignLeft">
|
||||
<widget class="QLabel" name="startLabel">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtSearchStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" alignment="Qt::AlignLeft">
|
||||
<item row="0" column="1" alignment="Qt::AlignmentFlag::AlignLeft">
|
||||
<widget class="QLineEdit" name="txtSearchStart">
|
||||
<property name="text">
|
||||
<string notr="true">0x00</string>
|
||||
@@ -180,6 +195,9 @@
|
||||
<property name="text">
|
||||
<string>End</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>txtSearchEnd</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
@@ -206,6 +224,17 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>txtSearchValue</tabstop>
|
||||
<tabstop>cmbSearchComparison</tabstop>
|
||||
<tabstop>cmbSearchType</tabstop>
|
||||
<tabstop>chkSearchHex</tabstop>
|
||||
<tabstop>txtSearchStart</tabstop>
|
||||
<tabstop>txtSearchEnd</tabstop>
|
||||
<tabstop>btnSearch</tabstop>
|
||||
<tabstop>btnFilterSearch</tabstop>
|
||||
<tabstop>listSearchResults</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -114,12 +114,30 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
|
||||
const ccc::ast::Enum& enumeration = type.as<ccc::ast::Enum>();
|
||||
|
||||
QComboBox* combo_box = new QComboBox(parent);
|
||||
for (s32 i = 0; i < (s32)enumeration.constants.size(); i++)
|
||||
bool named = false;
|
||||
|
||||
for (size_t i = 0; i < enumeration.constants.size(); i++)
|
||||
{
|
||||
combo_box->addItem(QString::fromStdString(enumeration.constants[i].second));
|
||||
QString text = QString::fromStdString(enumeration.constants[i].second);
|
||||
combo_box->addItem(text, enumeration.constants[i].first);
|
||||
if (enumeration.constants[i].first == value.toInt())
|
||||
combo_box->setCurrentIndex(i);
|
||||
{
|
||||
combo_box->setCurrentIndex(static_cast<int>(i));
|
||||
named = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!named)
|
||||
{
|
||||
// The value isn't equal to any of the named constants, so
|
||||
// add an extra item to the combo box representing the
|
||||
// current value so that the first named constant isn't
|
||||
// written back to VM memory accidentally.
|
||||
QString text = display_options.signedIntegerToString(value.toInt(), 32);
|
||||
combo_box->insertItem(0, text, value.toInt());
|
||||
combo_box->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
connect(combo_box, &QComboBox::currentIndexChanged, this, &SymbolTreeValueDelegate::onComboBoxIndexChanged);
|
||||
result = combo_box;
|
||||
|
||||
@@ -245,15 +263,10 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
|
||||
}
|
||||
case ccc::ast::ENUM:
|
||||
{
|
||||
const ccc::ast::Enum& enumeration = type.as<ccc::ast::Enum>();
|
||||
QComboBox* combo_box = qobject_cast<QComboBox*>(editor);
|
||||
Q_ASSERT(combo_box);
|
||||
|
||||
s32 comboIndex = combo_box->currentIndex();
|
||||
if (comboIndex < 0 || comboIndex >= (s32)enumeration.constants.size())
|
||||
break;
|
||||
|
||||
value = enumeration.constants[comboIndex].first;
|
||||
value = combo_box->currentData().toInt();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -390,15 +390,13 @@ QString SymbolTreeNode::generateDisplayString(
|
||||
}
|
||||
case ccc::ast::ENUM:
|
||||
{
|
||||
s32 value = (s32)location.read32(cpu);
|
||||
s32 value = static_cast<s32>(location.read32(cpu));
|
||||
const auto& enum_type = physical_type.as<ccc::ast::Enum>();
|
||||
for (auto [test_value, name] : enum_type.constants)
|
||||
{
|
||||
for (const auto& [test_value, name] : enum_type.constants)
|
||||
if (test_value == value)
|
||||
return QString::fromStdString(name);
|
||||
}
|
||||
|
||||
break;
|
||||
return display_options.signedIntegerToString(value, 32);
|
||||
}
|
||||
case ccc::ast::POINTER_OR_REFERENCE:
|
||||
{
|
||||
|
||||
@@ -29,20 +29,12 @@
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
|
||||
DisplayWidget::DisplayWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
DisplaySurface::DisplaySurface()
|
||||
: QWindow()
|
||||
{
|
||||
// We want a native window for both D3D and OpenGL.
|
||||
setAutoFillBackground(false);
|
||||
setAttribute(Qt::WA_NativeWindow, true);
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||
setAttribute(Qt::WA_KeyCompression, false);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
DisplayWidget::~DisplayWidget()
|
||||
DisplaySurface::~DisplaySurface()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (m_clip_mouse_enabled)
|
||||
@@ -50,19 +42,17 @@ DisplayWidget::~DisplayWidget()
|
||||
#endif
|
||||
}
|
||||
|
||||
int DisplayWidget::scaledWindowWidth() const
|
||||
QWidget* DisplaySurface::createWindowContainer(QWidget* parent)
|
||||
{
|
||||
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioF())), 1);
|
||||
m_container = QWidget::createWindowContainer(this, parent);
|
||||
m_container->installEventFilter(this);
|
||||
m_container->setFocusPolicy(Qt::StrongFocus);
|
||||
return m_container;
|
||||
}
|
||||
|
||||
int DisplayWidget::scaledWindowHeight() const
|
||||
std::optional<WindowInfo> DisplaySurface::getWindowInfo()
|
||||
{
|
||||
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioF())), 1);
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> DisplayWidget::getWindowInfo()
|
||||
{
|
||||
std::optional<WindowInfo> ret(QtUtils::GetWindowInfoForWidget(this));
|
||||
std::optional<WindowInfo> ret(QtUtils::GetWindowInfoForWindow(this));
|
||||
if (ret.has_value())
|
||||
{
|
||||
m_last_window_width = ret->surface_width;
|
||||
@@ -72,7 +62,7 @@ std::optional<WindowInfo> DisplayWidget::getWindowInfo()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DisplayWidget::updateRelativeMode(bool enabled)
|
||||
void DisplaySurface::updateRelativeMode(bool enabled)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// prefer ClipCursor() over warping movement when we're using raw input
|
||||
@@ -104,17 +94,17 @@ void DisplayWidget::updateRelativeMode(bool enabled)
|
||||
#endif
|
||||
m_relative_mouse_start_pos = QCursor::pos();
|
||||
updateCenterPos();
|
||||
grabMouse();
|
||||
setMouseGrabEnabled(true);
|
||||
}
|
||||
else if (m_relative_mouse_enabled)
|
||||
{
|
||||
m_relative_mouse_enabled = false;
|
||||
QCursor::setPos(m_relative_mouse_start_pos);
|
||||
releaseMouse();
|
||||
setMouseGrabEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayWidget::updateCursor(bool hidden)
|
||||
void DisplaySurface::updateCursor(bool hidden)
|
||||
{
|
||||
if (m_cursor_hidden == hidden)
|
||||
return;
|
||||
@@ -132,7 +122,7 @@ void DisplayWidget::updateCursor(bool hidden)
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayWidget::handleCloseEvent(QCloseEvent* event)
|
||||
void DisplaySurface::handleCloseEvent(QCloseEvent* event)
|
||||
{
|
||||
// Closing the separate widget will either cancel the close, or trigger shutdown.
|
||||
// In the latter case, it's going to destroy us, so don't let Qt do it first.
|
||||
@@ -152,28 +142,13 @@ void DisplayWidget::handleCloseEvent(QCloseEvent* event)
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void DisplayWidget::destroy()
|
||||
bool DisplaySurface::isActuallyFullscreen() const
|
||||
{
|
||||
m_destroying = true;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// See Qt documentation, entire application is in full screen state, and the main
|
||||
// window will get reopened fullscreen instead of windowed if we don't close the
|
||||
// fullscreen window first.
|
||||
if (isActuallyFullscreen())
|
||||
close();
|
||||
#endif
|
||||
deleteLater();
|
||||
// DisplaySurface is always in a container, so we need to check parent window
|
||||
return parent()->windowState() & Qt::WindowFullScreen;
|
||||
}
|
||||
|
||||
bool DisplayWidget::isActuallyFullscreen() const
|
||||
{
|
||||
// I hate you QtWayland... have to check the parent, not ourselves.
|
||||
QWidget* container = qobject_cast<QWidget*>(parent());
|
||||
return container ? container->isFullScreen() : isFullScreen();
|
||||
}
|
||||
|
||||
void DisplayWidget::updateCenterPos()
|
||||
void DisplaySurface::updateCenterPos()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (m_clip_mouse_enabled)
|
||||
@@ -203,12 +178,14 @@ void DisplayWidget::updateCenterPos()
|
||||
#endif
|
||||
}
|
||||
|
||||
QPaintEngine* DisplayWidget::paintEngine() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DisplayWidget::event(QEvent* event)
|
||||
// Keyboard focus and child windows are inconsistant across platforms;
|
||||
// Windows: Can programmatically focus the child window, NVidia overlay can defocus it.
|
||||
// X11: Can programmatically focus the child window.
|
||||
// Wayland: Child window cannot be focused at all on most(?) DE.
|
||||
// Mac: Can programmatically focus the child window.
|
||||
// Thus for KB inputs we need to sometimes use the event filter.
|
||||
// Mouse events are always delivered to the child window, so that seems consistant.
|
||||
void DisplaySurface::handleKeyInputEvent(QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
@@ -229,7 +206,7 @@ bool DisplayWidget::event(QEvent* event)
|
||||
}
|
||||
|
||||
if (key_event->isAutoRepeat())
|
||||
return true;
|
||||
return;
|
||||
|
||||
// For some reason, Windows sends "fake" key events.
|
||||
// Scenario: Press shift, press F1, release shift, release F1.
|
||||
@@ -246,7 +223,7 @@ bool DisplayWidget::event(QEvent* event)
|
||||
if (it != m_keys_pressed_with_modifiers.end())
|
||||
{
|
||||
if (pressed)
|
||||
return true;
|
||||
return;
|
||||
else
|
||||
m_keys_pressed_with_modifiers.erase(it);
|
||||
}
|
||||
@@ -259,6 +236,23 @@ bool DisplayWidget::event(QEvent* event)
|
||||
InputManager::InvokeEvents(InputManager::MakeHostKeyboardKey(key), static_cast<float>(pressed));
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
pxAssert(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplaySurface::event(QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
{
|
||||
handleKeyInputEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -268,7 +262,7 @@ bool DisplayWidget::event(QEvent* event)
|
||||
|
||||
if (!m_relative_mouse_enabled)
|
||||
{
|
||||
const qreal dpr = devicePixelRatioF();
|
||||
const qreal dpr = devicePixelRatio();
|
||||
const QPoint mouse_pos = mouse_event->pos();
|
||||
|
||||
const float scaled_x = static_cast<float>(static_cast<qreal>(mouse_pos.x()) * dpr);
|
||||
@@ -352,11 +346,11 @@ bool DisplayWidget::event(QEvent* event)
|
||||
case QEvent::DevicePixelRatioChange:
|
||||
case QEvent::Resize:
|
||||
{
|
||||
QWidget::event(event);
|
||||
QWindow::event(event);
|
||||
|
||||
const float dpr = devicePixelRatioF();
|
||||
const u32 scaled_width = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * dpr)), 1));
|
||||
const u32 scaled_height = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * dpr)), 1));
|
||||
const float dpr = devicePixelRatio();
|
||||
const u32 scaled_width = static_cast<u32>(std::max(static_cast<int>(std::round(static_cast<qreal>(width()) * dpr)), 1));
|
||||
const u32 scaled_height = static_cast<u32>(std::max(static_cast<int>(std::round(static_cast<qreal>(height()) * dpr)), 1));
|
||||
|
||||
// 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)
|
||||
@@ -371,106 +365,60 @@ bool DisplayWidget::event(QEvent* event)
|
||||
return true;
|
||||
}
|
||||
|
||||
case QEvent::DragEnter:
|
||||
QWindow::event(event);
|
||||
emit dragEnterEvent(static_cast<QDragEnterEvent*>(event));
|
||||
return event->isAccepted();
|
||||
|
||||
case QEvent::Drop:
|
||||
QWindow::event(event);
|
||||
emit dropEvent(static_cast<QDropEvent*>(event));
|
||||
return event->isAccepted();
|
||||
|
||||
case QEvent::Move:
|
||||
{
|
||||
updateCenterPos();
|
||||
return true;
|
||||
}
|
||||
|
||||
case QEvent::Close:
|
||||
{
|
||||
if (m_destroying)
|
||||
return QWidget::event(event);
|
||||
|
||||
handleCloseEvent(static_cast<QCloseEvent*>(event));
|
||||
return true;
|
||||
}
|
||||
|
||||
case QEvent::WindowStateChange:
|
||||
{
|
||||
QWidget::event(event);
|
||||
|
||||
if (static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized)
|
||||
emit windowRestoredEvent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return QWidget::event(event);
|
||||
return QWindow::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayContainer::DisplayContainer()
|
||||
: QStackedWidget(nullptr)
|
||||
bool DisplaySurface::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
}
|
||||
|
||||
DisplayContainer::~DisplayContainer() = default;
|
||||
|
||||
bool DisplayContainer::isNeeded(bool fullscreen, bool render_to_main)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
return false;
|
||||
#else
|
||||
if (!isRunningOnWayland())
|
||||
return false;
|
||||
|
||||
// We only need this on Wayland because of client-side decorations...
|
||||
return (fullscreen || !render_to_main);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DisplayContainer::isRunningOnWayland()
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
return false;
|
||||
#else
|
||||
const QString platform_name = QGuiApplication::platformName();
|
||||
return (platform_name == QStringLiteral("wayland"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void DisplayContainer::setDisplayWidget(DisplayWidget* widget)
|
||||
{
|
||||
pxAssert(!m_display_widget);
|
||||
m_display_widget = widget;
|
||||
addWidget(widget);
|
||||
}
|
||||
|
||||
DisplayWidget* DisplayContainer::removeDisplayWidget()
|
||||
{
|
||||
DisplayWidget* widget = m_display_widget;
|
||||
pxAssert(widget);
|
||||
m_display_widget = nullptr;
|
||||
removeWidget(widget);
|
||||
return widget;
|
||||
}
|
||||
|
||||
bool DisplayContainer::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Close && m_display_widget)
|
||||
{
|
||||
m_display_widget->handleCloseEvent(static_cast<QCloseEvent*>(event));
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool res = QStackedWidget::event(event);
|
||||
if (!m_display_widget)
|
||||
return res;
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
#ifdef _WIN32
|
||||
// Nvidia overlay causes the child window to lose focus, but not its parent.
|
||||
// Refocus the child window.
|
||||
requestActivate();
|
||||
#endif
|
||||
handleKeyInputEvent(event);
|
||||
return true;
|
||||
|
||||
// These events only work on the top level control.
|
||||
// Which is this container when render to seperate or fullscreen is active.
|
||||
case QEvent::Close:
|
||||
handleCloseEvent(static_cast<QCloseEvent*>(event));
|
||||
return true;
|
||||
case QEvent::WindowStateChange:
|
||||
{
|
||||
if (static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized)
|
||||
emit m_display_widget->windowRestoredEvent();
|
||||
}
|
||||
break;
|
||||
emit windowRestoredEvent();
|
||||
return false;
|
||||
|
||||
case QEvent::ChildRemoved:
|
||||
if (static_cast<QChildEvent*>(event)->child() == m_container)
|
||||
{
|
||||
object->removeEventFilter(this);
|
||||
m_container = nullptr;
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3,40 +3,44 @@
|
||||
|
||||
#pragma once
|
||||
#include "common/WindowInfo.h"
|
||||
#include <QtWidgets/QStackedWidget>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtGui/QDragMoveEvent>
|
||||
#include <QtGui/QWindow>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
class QCloseEvent;
|
||||
|
||||
class DisplayWidget final : public QWidget
|
||||
class DisplaySurface final : public QWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DisplayWidget(QWidget* parent);
|
||||
~DisplayWidget();
|
||||
explicit DisplaySurface();
|
||||
~DisplaySurface();
|
||||
|
||||
QPaintEngine* paintEngine() const override;
|
||||
|
||||
int scaledWindowWidth() const;
|
||||
int scaledWindowHeight() const;
|
||||
// while QWindow can be used directly as a window, Popups requre a QWidget parent.
|
||||
// Additionally, we use saveGeometry/restoreGeometry for render to seperate window mode
|
||||
// but those functions only exist on QWidget.
|
||||
// Thus, we always need a container widget.
|
||||
QWidget* createWindowContainer(QWidget* parent = nullptr);
|
||||
|
||||
std::optional<WindowInfo> getWindowInfo();
|
||||
|
||||
void updateRelativeMode(bool enabled);
|
||||
void updateCursor(bool hidden);
|
||||
|
||||
void handleCloseEvent(QCloseEvent* event);
|
||||
void destroy();
|
||||
|
||||
Q_SIGNALS:
|
||||
void windowResizedEvent(int width, int height, float scale);
|
||||
void windowRestoredEvent();
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent* event);
|
||||
void dropEvent(QDropEvent* event);
|
||||
|
||||
protected:
|
||||
void handleCloseEvent(QCloseEvent* event);
|
||||
void handleKeyInputEvent(QEvent* event);
|
||||
bool event(QEvent* event) override;
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
private:
|
||||
bool isActuallyFullscreen() const;
|
||||
@@ -49,34 +53,12 @@ private:
|
||||
bool m_clip_mouse_enabled = false;
|
||||
#endif
|
||||
bool m_cursor_hidden = false;
|
||||
bool m_destroying = false;
|
||||
|
||||
std::vector<int> m_keys_pressed_with_modifiers;
|
||||
|
||||
u32 m_last_window_width = 0;
|
||||
u32 m_last_window_height = 0;
|
||||
float m_last_window_scale = 1.0f;
|
||||
};
|
||||
|
||||
class DisplayContainer final : public QStackedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DisplayContainer();
|
||||
~DisplayContainer();
|
||||
|
||||
// Wayland is broken in lots of ways, so we need to check for it.
|
||||
static bool isRunningOnWayland();
|
||||
|
||||
static bool isNeeded(bool fullscreen, bool render_to_main);
|
||||
|
||||
void setDisplayWidget(DisplayWidget* widget);
|
||||
DisplayWidget* removeDisplayWidget();
|
||||
|
||||
protected:
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
DisplayWidget* m_display_widget = nullptr;
|
||||
|
||||
QWidget* m_container = nullptr;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -30,7 +30,7 @@
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">No games in supported formats were found.</span></p><p>Please add a directory with games to begin.</p><p>Game dumps in the following formats will be scanned and listed:</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -40,7 +40,7 @@
|
||||
<string notr="true">TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -49,7 +49,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -69,7 +69,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -86,7 +86,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -106,7 +106,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -121,7 +121,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -133,6 +133,10 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>addGameDirectory</tabstop>
|
||||
<tabstop>scanForNewGames</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -23,53 +23,14 @@ static constexpr std::array<const char*, GameListModel::Column_Count> s_column_n
|
||||
static constexpr int COVER_ART_WIDTH = 350;
|
||||
static constexpr int COVER_ART_HEIGHT = 512;
|
||||
static constexpr int COVER_ART_SPACING = 32;
|
||||
|
||||
// Scaling these is not a linear transform due to float conversions; add them together here.
|
||||
static constexpr int SIZE_HINT_WIDTH = COVER_ART_WIDTH + (COVER_ART_SPACING / 2);
|
||||
static constexpr int SIZE_HINT_HEIGHT = COVER_ART_HEIGHT + (COVER_ART_SPACING / 2);
|
||||
static constexpr int SIZE_HINT_HEIGHT_TITLES = SIZE_HINT_HEIGHT + COVER_ART_SPACING;
|
||||
|
||||
static constexpr int MIN_COVER_CACHE_SIZE = 256;
|
||||
|
||||
static int DPRScale(int size, qreal dpr)
|
||||
{
|
||||
return static_cast<int>(static_cast<qreal>(size) * dpr);
|
||||
}
|
||||
|
||||
static int DPRUnscale(int size, qreal dpr)
|
||||
{
|
||||
return static_cast<int>(static_cast<qreal>(size) / dpr);
|
||||
}
|
||||
|
||||
static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_height, qreal dpr)
|
||||
{
|
||||
const int dpr_expected_width = DPRScale(expected_width, dpr);
|
||||
const int dpr_expected_height = DPRScale(expected_height, dpr);
|
||||
if (pm->width() == dpr_expected_width && pm->height() == dpr_expected_height)
|
||||
return;
|
||||
|
||||
*pm = pm->scaled(dpr_expected_width, dpr_expected_height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
if (pm->width() == dpr_expected_width && pm->height() == dpr_expected_height)
|
||||
return;
|
||||
|
||||
// QPainter works in unscaled coordinates.
|
||||
int xoffs = 0;
|
||||
int yoffs = 0;
|
||||
if (pm->width() < dpr_expected_width)
|
||||
xoffs = DPRUnscale((dpr_expected_width - pm->width()) / 2, dpr);
|
||||
if (pm->height() < dpr_expected_height)
|
||||
yoffs = DPRUnscale((dpr_expected_height - pm->height()) / 2, dpr);
|
||||
|
||||
QPixmap padded_image(dpr_expected_width, dpr_expected_height);
|
||||
padded_image.setDevicePixelRatio(dpr);
|
||||
padded_image.fill(Qt::transparent);
|
||||
QPainter painter;
|
||||
if (painter.begin(&padded_image))
|
||||
{
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.drawPixmap(xoffs, yoffs, *pm);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Destination);
|
||||
painter.fillRect(padded_image.rect(), QColor(0, 0, 0, 0));
|
||||
painter.end();
|
||||
}
|
||||
|
||||
*pm = padded_image;
|
||||
}
|
||||
|
||||
static QPixmap createPlaceholderImage(const QPixmap& placeholder_pixmap, int width, int height, float scale,
|
||||
qreal dpr, const std::string& title)
|
||||
{
|
||||
@@ -78,7 +39,7 @@ static QPixmap createPlaceholderImage(const QPixmap& placeholder_pixmap, int wid
|
||||
if (pm.isNull())
|
||||
return QPixmap();
|
||||
|
||||
resizeAndPadPixmap(&pm, width, height, dpr);
|
||||
QtUtils::resizeAndScalePixmap(&pm, width, height, dpr, QtUtils::ScalingMode::Fit, 100);
|
||||
QPainter painter;
|
||||
if (painter.begin(&pm))
|
||||
{
|
||||
@@ -96,9 +57,9 @@ static QPixmap createPlaceholderImage(const QPixmap& placeholder_pixmap, int wid
|
||||
return pm;
|
||||
}
|
||||
|
||||
std::optional<GameListModel::Column> GameListModel::getColumnIdForName(std::string_view name)
|
||||
std::optional<GameListModel::Column> GameListModel::getColumnIdForName(const std::string_view name)
|
||||
{
|
||||
for (int column = 0; column < Column_Count; column++)
|
||||
for (u32 column = 0; column < Column_Count; column++)
|
||||
{
|
||||
if (name == s_column_names[column])
|
||||
return static_cast<Column>(column);
|
||||
@@ -107,12 +68,12 @@ std::optional<GameListModel::Column> GameListModel::getColumnIdForName(std::stri
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const char* GameListModel::getColumnName(Column col)
|
||||
const char* GameListModel::getColumnName(const Column col)
|
||||
{
|
||||
return s_column_names[static_cast<int>(col)];
|
||||
}
|
||||
|
||||
GameListModel::GameListModel(float cover_scale, bool show_cover_titles, qreal dpr, QObject* parent /* = nullptr */)
|
||||
GameListModel::GameListModel(const float cover_scale, const bool show_cover_titles, const qreal dpr, QObject* parent /* = nullptr */)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_show_titles_for_covers(show_cover_titles)
|
||||
, m_dpr{dpr}
|
||||
@@ -175,29 +136,31 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
|
||||
|
||||
QFuture<QPixmap> future = QtConcurrent::run([this, entry = *ge, counter]() -> QPixmap {
|
||||
QPixmap image;
|
||||
|
||||
// Initial check that the scale is unchanged before we run costly image generation.
|
||||
if (m_cover_scale_counter.load(std::memory_order_acquire) == counter)
|
||||
{
|
||||
const std::string cover_path(GameList::GetCoverImagePathForEntry(&entry));
|
||||
if (!cover_path.empty())
|
||||
{
|
||||
image = QPixmap(QString::fromStdString(cover_path));
|
||||
if (!image.isNull())
|
||||
{
|
||||
image.setDevicePixelRatio(m_dpr);
|
||||
resizeAndPadPixmap(&image, getCoverArtWidth(), getCoverArtHeight(), m_dpr);
|
||||
}
|
||||
|
||||
// Create placeholder image if no user-provided cover exists.
|
||||
if (image.isNull())
|
||||
{
|
||||
const std::string& title = entry.GetTitle(m_prefer_english_titles);
|
||||
image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, m_dpr, title);
|
||||
}
|
||||
// Create resized image from user-provided cover.
|
||||
else
|
||||
{
|
||||
image.setDevicePixelRatio(m_dpr);
|
||||
QtUtils::resizeAndScalePixmap(&image, getCoverArtWidth(), getCoverArtHeight(), m_dpr, QtUtils::ScalingMode::Fit, 100);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& title = entry.GetTitle(m_prefer_english_titles);
|
||||
// Final check that scale is unchanged before we send out the produced image.
|
||||
return m_cover_scale_counter.load(std::memory_order_acquire) == counter ? image : QPixmap();
|
||||
|
||||
if (image.isNull())
|
||||
image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, m_dpr, title);
|
||||
|
||||
if (m_cover_scale_counter.load(std::memory_order_acquire) != counter)
|
||||
image = {};
|
||||
|
||||
return image;
|
||||
});
|
||||
|
||||
// Context must be 'this' so we run on the UI thread.
|
||||
@@ -213,25 +176,18 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
|
||||
void GameListModel::invalidateCoverForPath(const std::string& path)
|
||||
{
|
||||
// This isn't ideal, but not sure how else we can get the row, when it might change while scanning...
|
||||
auto lock = GameList::GetLock();
|
||||
const auto lock = GameList::GetLock();
|
||||
const u32 count = GameList::GetEntryCount();
|
||||
std::optional<u32> row;
|
||||
for (u32 i = 0; i < count; i++)
|
||||
|
||||
for (u32 row = 0; row < count; row++)
|
||||
{
|
||||
if (GameList::GetEntryByIndex(i)->path == path)
|
||||
if (GameList::GetEntryByIndex(row)->path == path)
|
||||
{
|
||||
row = i;
|
||||
break;
|
||||
const QModelIndex mi(index(row, Column_Cover));
|
||||
emit dataChanged(mi, mi, {Qt::DecorationRole});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!row.has_value())
|
||||
{
|
||||
// Game removed?
|
||||
return;
|
||||
}
|
||||
|
||||
const QModelIndex mi(index(static_cast<int>(row.value()), Column_Cover));
|
||||
emit dataChanged(mi, mi, {Qt::DecorationRole});
|
||||
}
|
||||
|
||||
int GameListModel::getCoverArtWidth() const
|
||||
@@ -251,45 +207,43 @@ int GameListModel::getCoverArtSpacing() const
|
||||
|
||||
int GameListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return static_cast<int>(GameList::GetEntryCount());
|
||||
return parent.isValid() ? 0 : static_cast<int>(GameList::GetEntryCount());
|
||||
}
|
||||
|
||||
int GameListModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return Column_Count;
|
||||
return parent.isValid() ? 0 : Column_Count;
|
||||
}
|
||||
|
||||
QString GameListModel::formatTimespan(time_t timespan)
|
||||
QString GameListModel::formatTimespan(const time_t timespan)
|
||||
{
|
||||
// avoid an extra string conversion
|
||||
// Avoid an extra string conversion over calling QString::fromStdString(GameList::FormatTimespan).
|
||||
const u32 hours = static_cast<u32>(timespan / 3600);
|
||||
const u32 minutes = static_cast<u32>((timespan % 3600) / 60);
|
||||
if (hours > 0)
|
||||
return qApp->translate("GameList", "%n hours", "", hours);
|
||||
else
|
||||
|
||||
const u32 minutes = static_cast<u32>((timespan % 3600) / 60);
|
||||
if (minutes > 0)
|
||||
return qApp->translate("GameList", "%n minutes", "", minutes);
|
||||
else
|
||||
return qApp->translate("GameList", "%n seconds", "", static_cast<u32>((timespan % 3600) % 60));
|
||||
}
|
||||
|
||||
QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||
QVariant GameListModel::data(const QModelIndex& index, const int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
return QVariant();
|
||||
|
||||
const int row = index.row();
|
||||
if (row < 0 || row >= static_cast<int>(GameList::GetEntryCount()))
|
||||
return {};
|
||||
return QVariant();
|
||||
|
||||
const auto lock = GameList::GetLock();
|
||||
const GameList::Entry* ge = GameList::GetEntryByIndex(row);
|
||||
if (!ge)
|
||||
return {};
|
||||
return QVariant();
|
||||
|
||||
// See: https://doc.qt.io/qt-6/qt.html#ItemDataRole-enum
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
@@ -309,12 +263,7 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||
return QString::fromStdString(fmt::format("{:08X}", ge->crc));
|
||||
|
||||
case Column_TimePlayed:
|
||||
{
|
||||
if (ge->total_played_time == 0)
|
||||
return {};
|
||||
else
|
||||
return formatTimespan(ge->total_played_time);
|
||||
}
|
||||
return ge->total_played_time ? formatTimespan(ge->total_played_time) : QVariant();
|
||||
|
||||
case Column_LastPlayed:
|
||||
return QString::fromStdString(GameList::FormatTimestamp(ge->last_played_time));
|
||||
@@ -323,55 +272,10 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||
return QString("%1 MB").arg(static_cast<double>(ge->total_size) / 1048576.0, 0, 'f', 2);
|
||||
|
||||
case Column_Cover:
|
||||
{
|
||||
if (m_show_titles_for_covers)
|
||||
return QString::fromStdString(ge->GetTitle(m_prefer_english_titles));
|
||||
else
|
||||
return {};
|
||||
}
|
||||
return m_show_titles_for_covers ? QString::fromStdString(ge->GetTitle(m_prefer_english_titles)) : QVariant();
|
||||
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
case Qt::InitialSortOrderRole:
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case Column_Type:
|
||||
return static_cast<int>(ge->type);
|
||||
|
||||
case Column_Serial:
|
||||
return QString::fromStdString(ge->serial);
|
||||
|
||||
case Column_Title:
|
||||
case Column_Cover:
|
||||
return QString::fromStdString(ge->GetTitleSort(m_prefer_english_titles));
|
||||
|
||||
case Column_FileTitle:
|
||||
return QtUtils::StringViewToQString(Path::GetFileTitle(ge->path));
|
||||
|
||||
case Column_CRC:
|
||||
return static_cast<int>(ge->crc);
|
||||
|
||||
case Column_TimePlayed:
|
||||
return static_cast<qlonglong>(ge->total_played_time);
|
||||
|
||||
case Column_LastPlayed:
|
||||
return static_cast<qlonglong>(ge->last_played_time);
|
||||
|
||||
case Column_Region:
|
||||
return static_cast<int>(ge->region);
|
||||
|
||||
case Column_Compatibility:
|
||||
return static_cast<int>(ge->compatibility_rating);
|
||||
|
||||
case Column_Size:
|
||||
return static_cast<qulonglong>(ge->total_size);
|
||||
|
||||
default:
|
||||
return {};
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,22 +284,16 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||
switch (index.column())
|
||||
{
|
||||
case Column_Type:
|
||||
{
|
||||
return m_type_pixmaps[static_cast<u32>(ge->type)];
|
||||
}
|
||||
|
||||
case Column_Region:
|
||||
{
|
||||
return m_region_pixmaps[static_cast<u32>(ge->region)];
|
||||
}
|
||||
|
||||
case Column_Compatibility:
|
||||
{
|
||||
return m_compatibility_pixmaps[static_cast<u32>(
|
||||
(static_cast<u32>(ge->compatibility_rating) >= GameList::CompatibilityRatingCount) ?
|
||||
GameList::CompatibilityRating::Unknown :
|
||||
ge->compatibility_rating)];
|
||||
}
|
||||
|
||||
case Column_Cover:
|
||||
{
|
||||
@@ -403,27 +301,38 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||
if (pm)
|
||||
return *pm;
|
||||
|
||||
// We insert the placeholder into the cache, so that we don't repeatedly
|
||||
// queue loading jobs for this game.
|
||||
// Insert the placeholder into the cache so we don't repeatedly queue loading jobs for this game.
|
||||
const_cast<GameListModel*>(this)->loadOrGenerateCover(ge);
|
||||
return *m_cover_pixmap_cache.Insert(ge->path, m_loading_pixmap);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return {};
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
case Qt::SizeHintRole:
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case Column_Cover:
|
||||
return QSize(static_cast<int>(static_cast<float>(SIZE_HINT_WIDTH) * m_cover_scale),
|
||||
static_cast<int>(static_cast<float>(m_show_titles_for_covers ? SIZE_HINT_HEIGHT_TITLES : SIZE_HINT_HEIGHT) * m_cover_scale));
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant GameListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
QVariant GameListModel::headerData(const int section, const Qt::Orientation orientation, const int role) const
|
||||
{
|
||||
if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0 || section >= Column_Count)
|
||||
return {};
|
||||
return QVariant();
|
||||
|
||||
return m_column_display_names[section];
|
||||
}
|
||||
@@ -435,7 +344,7 @@ void GameListModel::refresh()
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
bool GameListModel::titlesLessThan(int left_row, int right_row) const
|
||||
bool GameListModel::titlesLessThan(const int left_row, const int right_row) const
|
||||
{
|
||||
if (left_row < 0 || left_row >= static_cast<int>(GameList::GetEntryCount()) || right_row < 0 ||
|
||||
right_row >= static_cast<int>(GameList::GetEntryCount()))
|
||||
@@ -449,7 +358,7 @@ bool GameListModel::titlesLessThan(int left_row, int right_row) const
|
||||
QString::fromStdString(right->GetTitleSort(m_prefer_english_titles))) < 0;
|
||||
}
|
||||
|
||||
bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& right_index, int column) const
|
||||
bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& right_index, const int column) const
|
||||
{
|
||||
if (!left_index.isValid() || !right_index.isValid())
|
||||
return false;
|
||||
@@ -482,13 +391,12 @@ bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& r
|
||||
{
|
||||
if (left->serial == right->serial)
|
||||
return titlesLessThan(left_row, right_row);
|
||||
|
||||
return (StringUtil::Strcasecmp(left->serial.c_str(), right->serial.c_str()) < 0);
|
||||
}
|
||||
|
||||
case Column_Title:
|
||||
{
|
||||
return titlesLessThan(left_row, right_row);
|
||||
}
|
||||
|
||||
case Column_FileTitle:
|
||||
{
|
||||
@@ -505,6 +413,7 @@ bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& r
|
||||
{
|
||||
if (left->region == right->region)
|
||||
return titlesLessThan(left_row, right_row);
|
||||
|
||||
return (static_cast<int>(left->region) < static_cast<int>(right->region));
|
||||
}
|
||||
|
||||
@@ -558,7 +467,7 @@ void GameListModel::loadSettings()
|
||||
m_prefer_english_titles = Host::GetBaseBoolSettingValue("UI", "PreferEnglishGameList", false);
|
||||
}
|
||||
|
||||
QIcon GameListModel::getIconForType(GameList::EntryType type)
|
||||
QIcon GameListModel::getIconForType(const GameList::EntryType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
@@ -572,7 +481,7 @@ QIcon GameListModel::getIconForType(GameList::EntryType type)
|
||||
}
|
||||
}
|
||||
|
||||
QIcon GameListModel::getIconForRegion(GameList::Region region)
|
||||
QIcon GameListModel::getIconForRegion(const GameList::Region region)
|
||||
{
|
||||
return QIcon(
|
||||
QStringLiteral("%1/icons/flags/%2.svg").arg(QtHost::GetResourcesBasePath()).arg(GameList::RegionToString(region, false)));
|
||||
@@ -583,8 +492,8 @@ void GameListModel::loadThemeSpecificImages()
|
||||
for (u32 type = 0; type < static_cast<u32>(GameList::EntryType::Count); type++)
|
||||
m_type_pixmaps[type] = getIconForType(static_cast<GameList::EntryType>(type)).pixmap(QSize(24, 24), m_dpr);
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(GameList::Region::Count); i++)
|
||||
m_region_pixmaps[i] = getIconForRegion(static_cast<GameList::Region>(i)).pixmap(QSize(36, 26), m_dpr);
|
||||
for (u32 region = 0; region < static_cast<u32>(GameList::Region::Count); region++)
|
||||
m_region_pixmaps[region] = getIconForRegion(static_cast<GameList::Region>(region)).pixmap(QSize(36, 26), m_dpr);
|
||||
}
|
||||
|
||||
void GameListModel::loadCommonImages()
|
||||
@@ -592,8 +501,8 @@ void GameListModel::loadCommonImages()
|
||||
loadThemeSpecificImages();
|
||||
|
||||
const QString base_path(QtHost::GetResourcesBasePath());
|
||||
for (u32 i = 1; i < GameList::CompatibilityRatingCount; i++)
|
||||
m_compatibility_pixmaps[i] = QIcon((QStringLiteral("%1/icons/star-%2.svg").arg(base_path).arg(i - 1))).pixmap(QSize(88, 16), m_dpr);
|
||||
for (u32 rating = 1; rating < GameList::CompatibilityRatingCount; rating++)
|
||||
m_compatibility_pixmaps[rating] = QIcon((QStringLiteral("%1/icons/star-%2.svg").arg(base_path).arg(rating - 1))).pixmap(QSize(88, 16), m_dpr);
|
||||
|
||||
m_placeholder_pixmap.load(QStringLiteral("%1/cover-placeholder.png").arg(base_path));
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ private:
|
||||
void loadOrGenerateCover(const GameList::Entry* ge);
|
||||
void invalidateCoverForPath(const std::string& path);
|
||||
|
||||
static QString formatTimespan(time_t timespan);
|
||||
static QString formatTimespan(const time_t timespan);
|
||||
|
||||
float m_cover_scale = 0.0f;
|
||||
std::atomic<u32> m_cover_scale_counter{0};
|
||||
|
||||
@@ -4,14 +4,17 @@
|
||||
#include "GameListRefreshThread.h"
|
||||
|
||||
#include "pcsx2/GameList.h"
|
||||
#include "pcsx2/Host.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/ProgressCallback.h"
|
||||
#include "common/Timer.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
AsyncRefreshProgressCallback::AsyncRefreshProgressCallback(GameListRefreshThread* parent)
|
||||
AsyncRefreshProgressCallback::AsyncRefreshProgressCallback(bool popup_on_error, GameListRefreshThread* parent)
|
||||
: m_parent(parent)
|
||||
, m_popup_on_error(popup_on_error)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -57,17 +60,20 @@ void AsyncRefreshProgressCallback::SetTitle(const char* title)
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayError(const char* message)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QStringLiteral("Error"), QString::fromUtf8(message));
|
||||
if (m_popup_on_error)
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("GameListRefreshThread", "Error"), message);
|
||||
else
|
||||
ERROR_LOG("{}", message);
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayWarning(const char* message)
|
||||
{
|
||||
QMessageBox::warning(nullptr, QStringLiteral("Warning"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayInformation(const char* message)
|
||||
{
|
||||
QMessageBox::information(nullptr, QStringLiteral("Information"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayDebugMessage(const char* message)
|
||||
@@ -77,17 +83,18 @@ void AsyncRefreshProgressCallback::DisplayDebugMessage(const char* message)
|
||||
|
||||
void AsyncRefreshProgressCallback::ModalError(const char* message)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QStringLiteral("Error"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
bool AsyncRefreshProgressCallback::ModalConfirmation(const char* message)
|
||||
{
|
||||
return QMessageBox::question(nullptr, QStringLiteral("Question"), QString::fromUtf8(message)) == QMessageBox::Yes;
|
||||
pxFailRel("Not implemented.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::ModalInformation(const char* message)
|
||||
{
|
||||
QMessageBox::information(nullptr, QStringLiteral("Information"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::fireUpdate()
|
||||
@@ -95,9 +102,9 @@ void AsyncRefreshProgressCallback::fireUpdate()
|
||||
m_parent->refreshProgress(m_status_text, m_last_value, m_last_range);
|
||||
}
|
||||
|
||||
GameListRefreshThread::GameListRefreshThread(bool invalidate_cache)
|
||||
GameListRefreshThread::GameListRefreshThread(bool invalidate_cache, bool popup_on_error)
|
||||
: QThread()
|
||||
, m_progress(this)
|
||||
, m_progress(popup_on_error, this)
|
||||
, m_invalidate_cache(invalidate_cache)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class GameListRefreshThread;
|
||||
class AsyncRefreshProgressCallback : public BaseProgressCallback
|
||||
{
|
||||
public:
|
||||
AsyncRefreshProgressCallback(GameListRefreshThread* parent);
|
||||
AsyncRefreshProgressCallback(bool popup_on_error, GameListRefreshThread* parent);
|
||||
|
||||
void Cancel();
|
||||
|
||||
@@ -38,6 +38,7 @@ private:
|
||||
QString m_status_text;
|
||||
int m_last_range = 1;
|
||||
int m_last_value = 0;
|
||||
bool m_popup_on_error = false;
|
||||
};
|
||||
|
||||
class GameListRefreshThread final : public QThread
|
||||
@@ -45,7 +46,7 @@ class GameListRefreshThread final : public QThread
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GameListRefreshThread(bool invalidate_cache);
|
||||
GameListRefreshThread(bool invalidate_cache, bool popup_on_error);
|
||||
~GameListRefreshThread();
|
||||
|
||||
void cancel();
|
||||
@@ -60,4 +61,5 @@ protected:
|
||||
private:
|
||||
AsyncRefreshProgressCallback m_progress;
|
||||
bool m_invalidate_cache;
|
||||
bool m_popup_on_error;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "Settings/InterfaceSettingsWidget.h"
|
||||
#include "pcsx2/GameList.h"
|
||||
#include "pcsx2/Host.h"
|
||||
|
||||
@@ -44,6 +45,25 @@ static const char* SUPPORTED_FORMATS_STRING = QT_TRANSLATE_NOOP(GameListWidget,
|
||||
static constexpr float MIN_SCALE = 0.1f;
|
||||
static constexpr float MAX_SCALE = 2.0f;
|
||||
|
||||
static constexpr GameListModel::Column DEFAULT_SORT_COLUMN = GameListModel::Column_Title;
|
||||
static constexpr int DEFAULT_SORT_INDEX = static_cast<int>(DEFAULT_SORT_COLUMN);
|
||||
static constexpr Qt::SortOrder DEFAULT_SORT_ORDER = Qt::AscendingOrder;
|
||||
|
||||
static constexpr std::array<int, GameListModel::Column_Count> DEFAULT_COLUMN_WIDTHS = {{
|
||||
55, // type
|
||||
85, // code
|
||||
-1, // title
|
||||
-1, // file title
|
||||
75, // crc
|
||||
95, // time played
|
||||
90, // last played
|
||||
80, // size
|
||||
60, // region
|
||||
120 // compatibility
|
||||
}};
|
||||
static_assert(static_cast<int>(DEFAULT_COLUMN_WIDTHS.size()) <= GameListModel::Column_Count,
|
||||
"Game List: More default column widths than column types.");
|
||||
|
||||
class GameListSortModel final : public QSortFilterProxyModel
|
||||
{
|
||||
public:
|
||||
@@ -106,6 +126,7 @@ private:
|
||||
|
||||
namespace
|
||||
{
|
||||
// Used for Type, Region, and Compatibility columns to center icons; Qt::AlignCenter only works on DisplayRole (text).
|
||||
class GameListIconStyleDelegate final : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
@@ -115,62 +136,61 @@ namespace
|
||||
}
|
||||
~GameListIconStyleDelegate() = default;
|
||||
|
||||
// See: QStyledItemDelegate::paint(), QItemDelegate::drawDecoration(), and Qt::QStyleOptionViewItem.
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
|
||||
{
|
||||
// https://stackoverflow.com/questions/32216568/how-to-set-icon-center-in-qtableview
|
||||
Q_ASSERT(index.isValid());
|
||||
|
||||
// Draw the base item, with a blank icon
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.icon = QIcon();
|
||||
// Based on QStyledItemDelegate::paint()
|
||||
const QStyle* style = option.widget ? option.widget->style() : QApplication::style();
|
||||
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);
|
||||
// Draw highlight for cell.
|
||||
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &option, painter, option.widget);
|
||||
|
||||
// Fetch icon pixmap
|
||||
const QRect r = option.rect;
|
||||
const QPixmap pix = qvariant_cast<QPixmap>(index.data(Qt::DecorationRole));
|
||||
// Fetch icon pixmap and stop if no icon exists
|
||||
const QPixmap icon = qvariant_cast<QPixmap>(index.data(Qt::DecorationRole));
|
||||
|
||||
if (pix.isNull())
|
||||
if (icon.isNull())
|
||||
return;
|
||||
|
||||
const int pix_width = static_cast<int>(pix.width() / pix.devicePixelRatio());
|
||||
const int pix_height = static_cast<int>(pix.height() / pix.devicePixelRatio());
|
||||
|
||||
// Clip the pixmaps so they don't extend outside the column
|
||||
// Save painter state and restore later so clip setting doesn't persist across cell draws.
|
||||
painter->save();
|
||||
painter->setClipRect(option.rect);
|
||||
|
||||
// Draw the icon, using code derived from QItemDelegate::drawDecoration()
|
||||
const bool enabled = option.state & QStyle::State_Enabled;
|
||||
const QPoint p = QPoint((r.width() - pix_width) / 2, (r.height() - pix_height) / 2);
|
||||
// Clip pixmap so it doesn't extend outside the cell.
|
||||
const QRect rect = option.rect;
|
||||
painter->setClipRect(rect);
|
||||
|
||||
// Determine starting location of icon (Qt uses top-left origin).
|
||||
const int icon_width = static_cast<int>(static_cast<qreal>(icon.width()) / icon.devicePixelRatio());
|
||||
const int icon_height = static_cast<int>(static_cast<qreal>(icon.height()) / icon.devicePixelRatio());
|
||||
const QPoint icon_top_left = QPoint((rect.width() - icon_width) / 2, (rect.height() - icon_height) / 2);
|
||||
|
||||
// Change palette if the item is selected.
|
||||
if (option.state & QStyle::State_Selected)
|
||||
{
|
||||
// See QItemDelegate::selectedPixmap()
|
||||
// Set color based on whether cell is enabled.
|
||||
const bool enabled = option.state & QStyle::State_Enabled;
|
||||
QColor color = option.palette.color(enabled ? QPalette::Normal : QPalette::Disabled, QPalette::Highlight);
|
||||
color.setAlphaF(0.3f);
|
||||
|
||||
QString key = QString::fromStdString(fmt::format("{:016X}-{:d}-{:08X}", pix.cacheKey(), enabled, color.rgba()));
|
||||
QPixmap pm;
|
||||
if (!QPixmapCache::find(key, &pm))
|
||||
// Fetch pixmap from cache or construct a new one.
|
||||
const QString key = QString::fromStdString(fmt::format("{:016X}-{:d}-{:08X}", icon.cacheKey(), enabled, color.rgba()));
|
||||
QPixmap highlighted_icon;
|
||||
if (!QPixmapCache::find(key, &highlighted_icon))
|
||||
{
|
||||
QImage img = pix.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
QImage img = icon.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QPainter tinted_painter(&img);
|
||||
tinted_painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
|
||||
tinted_painter.fillRect(0, 0, img.width(), img.height(), color);
|
||||
tinted_painter.end();
|
||||
|
||||
pm = QPixmap(QPixmap::fromImage(img));
|
||||
QPixmapCache::insert(key, pm);
|
||||
highlighted_icon = QPixmap(QPixmap::fromImage(img));
|
||||
QPixmapCache::insert(key, highlighted_icon);
|
||||
}
|
||||
|
||||
painter->drawPixmap(r.topLeft() + p, pm);
|
||||
painter->drawPixmap(rect.topLeft() + icon_top_left, highlighted_icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->drawPixmap(r.topLeft() + p, pix);
|
||||
painter->drawPixmap(rect.topLeft() + icon_top_left, icon);
|
||||
}
|
||||
|
||||
// Restore the old clip path.
|
||||
@@ -234,33 +254,46 @@ 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);
|
||||
m_table_view->setAlternatingRowColors(true);
|
||||
m_table_view->setMouseTracking(true);
|
||||
m_table_view->setShowGrid(false);
|
||||
m_table_view->setCurrentIndex({});
|
||||
m_table_view->setCurrentIndex(QModelIndex());
|
||||
m_table_view->horizontalHeader()->setHighlightSections(false);
|
||||
m_table_view->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_table_view->verticalHeader()->hide();
|
||||
m_table_view->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
|
||||
|
||||
// Custom painter to center-align DisplayRoles (icons)
|
||||
m_table_view->setItemDelegateForColumn(0, new GameListIconStyleDelegate(this));
|
||||
m_table_view->setItemDelegateForColumn(8, new GameListIconStyleDelegate(this));
|
||||
m_table_view->setItemDelegateForColumn(9, new GameListIconStyleDelegate(this));
|
||||
|
||||
loadTableViewColumnVisibilitySettings();
|
||||
loadTableViewColumnSortSettings();
|
||||
|
||||
connect(m_table_view->selectionModel(), &QItemSelectionModel::currentChanged, this,
|
||||
&GameListWidget::onSelectionModelCurrentChanged);
|
||||
connect(m_table_view, &QTableView::activated, this, &GameListWidget::onTableViewItemActivated);
|
||||
connect(m_table_view, &QTableView::customContextMenuRequested, this,
|
||||
&GameListWidget::onTableViewContextMenuRequested);
|
||||
connect(m_table_view->horizontalHeader(), &QHeaderView::customContextMenuRequested, this,
|
||||
&GameListWidget::onTableViewHeaderContextMenuRequested);
|
||||
&GameListWidget::onTableViewHeaderContextMenuRequested);
|
||||
|
||||
// Save state when header state changes (hiding and showing handled within onTableViewHeaderContextMenuRequested).
|
||||
connect(m_table_view->horizontalHeader(), &QHeaderView::sectionMoved, this, &GameListWidget::onTableHeaderStateChanged);
|
||||
connect(m_table_view->horizontalHeader(), &QHeaderView::sectionResized, this, &GameListWidget::onTableHeaderStateChanged);
|
||||
connect(m_table_view->horizontalHeader(), &QHeaderView::sortIndicatorChanged, this,
|
||||
&GameListWidget::onTableViewHeaderSortIndicatorChanged);
|
||||
[this](const int column, const Qt::SortOrder sort_order) { GameListWidget::saveSortSettings(column, sort_order); GameListWidget::onTableHeaderStateChanged(); });
|
||||
|
||||
// Load the last session's header state or create a new one.
|
||||
if (Host::ContainsBaseSettingValue("GameListTableView", "HeaderState"))
|
||||
loadTableHeaderState();
|
||||
else
|
||||
applyTableHeaderDefaults();
|
||||
|
||||
// After header state load to account for user-specified sort.
|
||||
m_table_view->setSortingEnabled(true);
|
||||
|
||||
m_ui.stack->insertWidget(0, m_table_view);
|
||||
|
||||
@@ -292,7 +325,7 @@ void GameListWidget::initialize()
|
||||
m_empty_ui.setupUi(m_empty_widget);
|
||||
m_empty_ui.supportedFormats->setText(qApp->translate("GameListWidget", SUPPORTED_FORMATS_STRING));
|
||||
connect(m_empty_ui.addGameDirectory, &QPushButton::clicked, this, [this]() { emit addGameDirectoryRequested(); });
|
||||
connect(m_empty_ui.scanForNewGames, &QPushButton::clicked, this, [this]() { refresh(false); });
|
||||
connect(m_empty_ui.scanForNewGames, &QPushButton::clicked, this, [this]() { refresh(false, true); });
|
||||
connect(qApp, &QGuiApplication::applicationStateChanged, this, [this]() { GameListWidget::updateCustomBackgroundState(); });
|
||||
m_ui.stack->insertWidget(2, m_empty_widget);
|
||||
|
||||
@@ -308,84 +341,30 @@ void GameListWidget::initialize()
|
||||
setCustomBackground();
|
||||
}
|
||||
|
||||
static void resizeAndPadImage(QImage* image, int expected_width, int expected_height, bool fill_with_top_left, bool expand_to_fill)
|
||||
void GameListWidget::setCustomBackground()
|
||||
{
|
||||
const qreal dpr = image->devicePixelRatio();
|
||||
const int dpr_expected_width = static_cast<int>(static_cast<qreal>(expected_width) * dpr);
|
||||
const int dpr_expected_height = static_cast<int>(static_cast<qreal>(expected_height) * dpr);
|
||||
if (image->width() == dpr_expected_width && image->height() == dpr_expected_height)
|
||||
return;
|
||||
|
||||
// Resize
|
||||
if (((static_cast<float>(image->width()) / static_cast<float>(image->height())) >=
|
||||
(static_cast<float>(dpr_expected_width) / static_cast<float>(dpr_expected_height))) != expand_to_fill)
|
||||
{
|
||||
*image = image->scaledToWidth(dpr_expected_width, Qt::SmoothTransformation);
|
||||
}
|
||||
else
|
||||
{
|
||||
*image = image->scaledToHeight(dpr_expected_height, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
if (image->width() == dpr_expected_width && image->height() == dpr_expected_height)
|
||||
return;
|
||||
|
||||
// Padding
|
||||
int xoffs = 0;
|
||||
int yoffs = 0;
|
||||
const int image_width = image->width();
|
||||
const int image_height = image->height();
|
||||
if ((image_width < dpr_expected_width) != expand_to_fill)
|
||||
xoffs = static_cast<int>(static_cast<qreal>((dpr_expected_width - image_width) / 2) / dpr);
|
||||
if ((image_height < dpr_expected_height) != expand_to_fill)
|
||||
yoffs = static_cast<int>(static_cast<qreal>((dpr_expected_height - image_height) / 2) / dpr);
|
||||
|
||||
QImage padded_image(dpr_expected_width, dpr_expected_height, QImage::Format_ARGB32);
|
||||
padded_image.setDevicePixelRatio(dpr);
|
||||
if (fill_with_top_left)
|
||||
padded_image.fill(image->pixel(0, 0));
|
||||
else
|
||||
padded_image.fill(Qt::transparent);
|
||||
|
||||
// Painting
|
||||
QPainter painter;
|
||||
const float opacity = Host::GetBaseFloatSettingValue("UI", "GameListBackgroundOpacity");
|
||||
if (painter.begin(&padded_image))
|
||||
{
|
||||
painter.setOpacity((static_cast<float>(opacity / 100.0f))); // Qt expects the range to be from 0.0 to 1.0
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.drawImage(xoffs, yoffs, *image);
|
||||
painter.end();
|
||||
}
|
||||
|
||||
*image = std::move(padded_image);
|
||||
}
|
||||
|
||||
void GameListWidget::setCustomBackground(bool force_refresh)
|
||||
{
|
||||
std::string path = Host::GetBaseStringSettingValue("UI", "GameListBackgroundPath");
|
||||
bool enabled = Host::GetBaseBoolSettingValue("UI", "GameListBackgroundEnabled");
|
||||
bool fill = Host::GetBaseBoolSettingValue("UI", "GameListBackgroundFill");
|
||||
|
||||
// Cleanup old animation if it still exists on gamelist
|
||||
if (m_background_movie != nullptr)
|
||||
{
|
||||
m_background_movie->disconnect(this);
|
||||
delete m_background_movie;
|
||||
m_background_movie = nullptr;
|
||||
}
|
||||
|
||||
std::string path = Host::GetBaseStringSettingValue("UI", "GameListBackgroundPath");
|
||||
if (!Path::IsAbsolute(path))
|
||||
path = Path::Combine(EmuFolders::DataRoot, path);
|
||||
|
||||
// Only try to create background both if path are valid and custom background are enabled
|
||||
if ((!path.empty() && FileSystem::FileExists(path.c_str())) && enabled)
|
||||
// Only try to create background if path are valid
|
||||
if (!path.empty() && FileSystem::FileExists(path.c_str()))
|
||||
{
|
||||
QMovie* new_movie;
|
||||
if (Path::GetExtension(path) == "png")
|
||||
QString img_path = QString::fromStdString(path);
|
||||
if (img_path.endsWith(".png", Qt::CaseInsensitive))
|
||||
// Use apng plugin
|
||||
new_movie = new QMovie(QString::fromStdString(path), "apng", this);
|
||||
new_movie = new QMovie(img_path, "apng", this);
|
||||
else
|
||||
new_movie = new QMovie(QString::fromStdString(path), QByteArray(), this);
|
||||
new_movie = new QMovie(img_path, QByteArray(), this);
|
||||
|
||||
if (new_movie->isValid())
|
||||
m_background_movie = new_movie;
|
||||
@@ -396,7 +375,7 @@ void GameListWidget::setCustomBackground(bool force_refresh)
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no valid background then reset fallback to UI state
|
||||
// If there is no valid background then reset fallback to default UI state
|
||||
if (!m_background_movie)
|
||||
{
|
||||
m_ui.stack->setPalette(QApplication::palette());
|
||||
@@ -404,36 +383,60 @@ void GameListWidget::setCustomBackground(bool force_refresh)
|
||||
return;
|
||||
}
|
||||
|
||||
// Background is valid, connect the signals and start animation in gamelist
|
||||
connect(m_background_movie, &QMovie::frameChanged, this, [this, fill]() { processBackgroundFrames(fill); });
|
||||
updateCustomBackgroundState(force_refresh);
|
||||
// Retrieve scaling setting
|
||||
m_background_scaling = QtUtils::ScalingMode::Fit;
|
||||
const std::string ar_value = Host::GetBaseStringSettingValue("UI", "GameListBackgroundMode", InterfaceSettingsWidget::BACKGROUND_SCALE_NAMES[static_cast<u8>(QtUtils::ScalingMode::Fit)]);
|
||||
for (u8 i = 0; i < static_cast<u8>(QtUtils::ScalingMode::MaxCount); i++)
|
||||
{
|
||||
if (!(InterfaceSettingsWidget::BACKGROUND_SCALE_NAMES[i] == nullptr))
|
||||
{
|
||||
if (ar_value == InterfaceSettingsWidget::BACKGROUND_SCALE_NAMES[i])
|
||||
{
|
||||
m_background_scaling = static_cast<QtUtils::ScalingMode>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve opacity setting
|
||||
m_background_opacity = Host::GetBaseFloatSettingValue("UI", "GameListBackgroundOpacity", 100.0f);
|
||||
|
||||
// Selected Custom background is valid, connect the signals and start animation in gamelist
|
||||
connect(m_background_movie, &QMovie::frameChanged, this, &GameListWidget::processBackgroundFrames, Qt::UniqueConnection);
|
||||
updateCustomBackgroundState(true);
|
||||
m_table_view->setAlternatingRowColors(false);
|
||||
}
|
||||
|
||||
void GameListWidget::updateCustomBackgroundState(bool force_start)
|
||||
void GameListWidget::updateCustomBackgroundState(const bool force_start)
|
||||
{
|
||||
if (m_background_movie)
|
||||
if (m_background_movie && m_background_movie->isValid())
|
||||
{
|
||||
if ((isVisible() && (isActiveWindow() || force_start)) && qGuiApp->applicationState() == Qt::ApplicationActive)
|
||||
m_background_movie->start();
|
||||
m_background_movie->setPaused(false);
|
||||
else
|
||||
m_background_movie->stop();
|
||||
m_background_movie->setPaused(true);
|
||||
}
|
||||
}
|
||||
|
||||
void GameListWidget::processBackgroundFrames(bool fill_area)
|
||||
void GameListWidget::processBackgroundFrames()
|
||||
{
|
||||
QImage img = m_background_movie->currentImage();
|
||||
img.setDevicePixelRatio(devicePixelRatioF());
|
||||
const int widget_width = m_ui.stack->width();
|
||||
const int widget_height = m_ui.stack->height();
|
||||
if (m_background_movie && m_background_movie->isValid())
|
||||
{
|
||||
const int widget_width = m_ui.stack->width();
|
||||
const int widget_height = m_ui.stack->height();
|
||||
|
||||
resizeAndPadImage(&img, widget_width, widget_height, false, fill_area);
|
||||
if (widget_width <= 0 || widget_height <= 0)
|
||||
return;
|
||||
|
||||
QPalette new_palette(m_ui.stack->palette());
|
||||
new_palette.setBrush(QPalette::Base, img);
|
||||
m_ui.stack->setPalette(new_palette);
|
||||
QPixmap pm = m_background_movie->currentPixmap();
|
||||
const qreal dpr = devicePixelRatioF();
|
||||
|
||||
QtUtils::resizeAndScalePixmap(&pm, widget_width, widget_height, dpr, m_background_scaling, m_background_opacity);
|
||||
|
||||
QPalette bg_palette(m_ui.stack->palette());
|
||||
bg_palette.setBrush(QPalette::Base, pm);
|
||||
m_ui.stack->setPalette(bg_palette);
|
||||
}
|
||||
}
|
||||
|
||||
bool GameListWidget::isShowingGameList() const
|
||||
@@ -451,11 +454,11 @@ bool GameListWidget::getShowGridCoverTitles() const
|
||||
return m_model->getShowCoverTitles();
|
||||
}
|
||||
|
||||
void GameListWidget::refresh(bool invalidate_cache)
|
||||
void GameListWidget::refresh(bool invalidate_cache, bool popup_on_error)
|
||||
{
|
||||
cancelRefresh();
|
||||
|
||||
m_refresh_thread = new GameListRefreshThread(invalidate_cache);
|
||||
m_refresh_thread = new GameListRefreshThread(invalidate_cache, popup_on_error);
|
||||
connect(m_refresh_thread, &GameListRefreshThread::refreshProgress, this, &GameListWidget::onRefreshProgress,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_refresh_thread, &GameListRefreshThread::refreshComplete, this, &GameListWidget::onRefreshComplete,
|
||||
@@ -552,18 +555,24 @@ void GameListWidget::onListViewContextMenuRequested(const QPoint& point)
|
||||
void GameListWidget::onTableViewHeaderContextMenuRequested(const QPoint& point)
|
||||
{
|
||||
QMenu menu;
|
||||
QHeaderView* header = m_table_view->horizontalHeader();
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
int column_visual = 0;
|
||||
for (int column = 0; column < GameListModel::Column_Count; column++)
|
||||
{
|
||||
// The "cover" column is the game grid and cannot be hidden.
|
||||
if (column == GameListModel::Column_Cover)
|
||||
continue;
|
||||
|
||||
QAction* action = menu.addAction(m_model->getColumnDisplayName(column));
|
||||
column_visual = header->visualIndex(column);
|
||||
QAction* action = menu.addAction(m_model->getColumnDisplayName(column_visual));
|
||||
action->setCheckable(true);
|
||||
action->setChecked(!m_table_view->isColumnHidden(column));
|
||||
connect(action, &QAction::toggled, [this, column](bool enabled) {
|
||||
m_table_view->setColumnHidden(column, !enabled);
|
||||
saveTableViewColumnVisibilitySettings(column);
|
||||
action->setChecked(!m_table_view->isColumnHidden(column_visual));
|
||||
connect(action, &QAction::toggled, [this, column_visual](bool enabled) {
|
||||
m_table_view->setColumnHidden(column_visual, !enabled);
|
||||
onTableHeaderStateChanged();
|
||||
resizeTableViewColumnsToFit();
|
||||
});
|
||||
}
|
||||
@@ -571,11 +580,6 @@ void GameListWidget::onTableViewHeaderContextMenuRequested(const QPoint& point)
|
||||
menu.exec(m_table_view->mapToGlobal(point));
|
||||
}
|
||||
|
||||
void GameListWidget::onTableViewHeaderSortIndicatorChanged(int, Qt::SortOrder)
|
||||
{
|
||||
saveTableViewColumnSortSettings();
|
||||
}
|
||||
|
||||
void GameListWidget::onCoverScaleChanged()
|
||||
{
|
||||
m_model->updateCacheSize(width(), height());
|
||||
@@ -711,7 +715,7 @@ void GameListWidget::resizeEvent(QResizeEvent* event)
|
||||
QWidget::resizeEvent(event);
|
||||
resizeTableViewColumnsToFit();
|
||||
m_model->updateCacheSize(width(), height());
|
||||
setCustomBackground();
|
||||
processBackgroundFrames();
|
||||
}
|
||||
|
||||
bool GameListWidget::event(QEvent* event)
|
||||
@@ -729,126 +733,141 @@ bool GameListWidget::event(QEvent* event)
|
||||
void GameListWidget::resizeTableViewColumnsToFit()
|
||||
{
|
||||
QtUtils::ResizeColumnsForTableView(m_table_view, {
|
||||
45, // type
|
||||
80, // code
|
||||
-1, // title
|
||||
-1, // file title
|
||||
65, // crc
|
||||
80, // time played
|
||||
80, // last played
|
||||
80, // size
|
||||
60, // region
|
||||
120 // compatibility
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Type],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Serial],
|
||||
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],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Size],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Region],
|
||||
DEFAULT_COLUMN_WIDTHS[GameListModel::Column_Compatibility],
|
||||
});
|
||||
}
|
||||
|
||||
static std::string getColumnVisibilitySettingsKeyName(int column)
|
||||
void GameListWidget::loadTableHeaderState()
|
||||
{
|
||||
return StringUtil::StdStringFromFormat("Show%s",
|
||||
QHeaderView* header = m_table_view->horizontalHeader();
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
// Decode Base64 string from settings to QByteArray state.
|
||||
const std::string state_setting = Host::GetBaseStringSettingValue("GameListTableView", "HeaderState");
|
||||
if (state_setting.empty())
|
||||
return;
|
||||
|
||||
QSignalBlocker blocker(header);
|
||||
header->restoreState(QByteArray::fromBase64(QByteArray::fromStdString(state_setting)));
|
||||
}
|
||||
|
||||
void GameListWidget::onTableHeaderStateChanged()
|
||||
{
|
||||
QHeaderView* header = m_table_view->horizontalHeader();
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
// Encode QByteArray state as Base64 string for storage.
|
||||
Host::SetBaseStringSettingValue("GameListTableView", "HeaderState", header->saveState().toBase64());
|
||||
}
|
||||
|
||||
void GameListWidget::applyTableHeaderDefaults()
|
||||
{
|
||||
QHeaderView* header = m_table_view->horizontalHeader();
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
{
|
||||
QSignalBlocker blocker(header);
|
||||
header->hideSection(GameListModel::Column_FileTitle);
|
||||
header->hideSection(GameListModel::Column_CRC);
|
||||
header->hideSection(GameListModel::Column_Cover);
|
||||
for (int column = 0; column < GameListModel::Column_Count; column++)
|
||||
{
|
||||
if (column == GameListModel::Column_Cover)
|
||||
continue;
|
||||
|
||||
header->resizeSection(column, DEFAULT_COLUMN_WIDTHS[column]);
|
||||
}
|
||||
header->setSortIndicator(DEFAULT_SORT_INDEX, DEFAULT_SORT_ORDER);
|
||||
}
|
||||
|
||||
Host::SetBaseStringSettingValue("GameListTableView", "HeaderState", header->saveState().toBase64());
|
||||
}
|
||||
|
||||
// TODO (Tech): Create a button for this in the minibar. Currently unused.
|
||||
void GameListWidget::resetTableHeaderToDefault()
|
||||
{
|
||||
QHeaderView* header = m_table_view->horizontalHeader();
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
{
|
||||
QSignalBlocker blocker(header);
|
||||
for (int column = 0; column < GameListModel::Column_Count; column++)
|
||||
{
|
||||
if (column == GameListModel::Column_Cover)
|
||||
continue;
|
||||
|
||||
// Reset size, position, and visibility.
|
||||
header->resizeSection(column, DEFAULT_COLUMN_WIDTHS[column]);
|
||||
header->moveSection(header->visualIndex(column), column);
|
||||
header->setSectionHidden(column,
|
||||
column == GameListModel::Column_CRC || column == GameListModel::Column_FileTitle);
|
||||
}
|
||||
header->hideSection(GameListModel::Column_Cover);
|
||||
header->setSortIndicator(DEFAULT_SORT_INDEX, DEFAULT_SORT_ORDER);
|
||||
}
|
||||
|
||||
Host::SetBaseStringSettingValue("GameListTableView", "HeaderState", header->saveState().toBase64());
|
||||
}
|
||||
|
||||
void GameListWidget::saveSortSettings(const int column, const Qt::SortOrder sort_order)
|
||||
{
|
||||
Host::SetBaseStringSettingValue("GameListTableView", "SortColumn",
|
||||
GameListModel::getColumnName(static_cast<GameListModel::Column>(column)));
|
||||
Host::SetBaseBoolSettingValue("GameListTableView", "SortDescending", static_cast<bool>(sort_order));
|
||||
}
|
||||
|
||||
void GameListWidget::loadTableViewColumnVisibilitySettings()
|
||||
std::optional<GameList::Entry> GameListWidget::getSelectedEntry() const
|
||||
{
|
||||
static constexpr std::array<bool, GameListModel::Column_Count> DEFAULT_VISIBILITY = {{
|
||||
true, // type
|
||||
true, // code
|
||||
true, // title
|
||||
false, // file title
|
||||
false, // crc
|
||||
true, // time played
|
||||
true, // last played
|
||||
true, // size
|
||||
true, // region
|
||||
true // compatibility
|
||||
}};
|
||||
auto lock = GameList::GetLock();
|
||||
|
||||
for (int column = 0; column < GameListModel::Column_Count; column++)
|
||||
{
|
||||
const bool visible = Host::GetBaseBoolSettingValue(
|
||||
"GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), DEFAULT_VISIBILITY[column]);
|
||||
m_table_view->setColumnHidden(column, !visible);
|
||||
}
|
||||
}
|
||||
|
||||
void GameListWidget::saveTableViewColumnVisibilitySettings()
|
||||
{
|
||||
for (int column = 0; column < GameListModel::Column_Count; column++)
|
||||
{
|
||||
const bool visible = !m_table_view->isColumnHidden(column);
|
||||
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), visible);
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
}
|
||||
|
||||
void GameListWidget::saveTableViewColumnVisibilitySettings(int column)
|
||||
{
|
||||
const bool visible = !m_table_view->isColumnHidden(column);
|
||||
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), visible);
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
|
||||
void GameListWidget::loadTableViewColumnSortSettings()
|
||||
{
|
||||
const GameListModel::Column DEFAULT_SORT_COLUMN = GameListModel::Column_Type;
|
||||
const bool DEFAULT_SORT_DESCENDING = false;
|
||||
|
||||
const GameListModel::Column sort_column =
|
||||
GameListModel::getColumnIdForName(Host::GetBaseStringSettingValue("GameListTableView", "SortColumn"))
|
||||
.value_or(DEFAULT_SORT_COLUMN);
|
||||
const bool sort_descending =
|
||||
Host::GetBaseBoolSettingValue("GameListTableView", "SortDescending", DEFAULT_SORT_DESCENDING);
|
||||
const Qt::SortOrder sort_order = sort_descending ? Qt::DescendingOrder : Qt::AscendingOrder;
|
||||
m_sort_model->sort(sort_column, sort_order);
|
||||
if (QHeaderView* hv = m_table_view->horizontalHeader())
|
||||
hv->setSortIndicator(sort_column, sort_order);
|
||||
}
|
||||
|
||||
void GameListWidget::saveTableViewColumnSortSettings()
|
||||
{
|
||||
const int sort_column = m_table_view->horizontalHeader()->sortIndicatorSection();
|
||||
const bool sort_descending = (m_table_view->horizontalHeader()->sortIndicatorOrder() == Qt::DescendingOrder);
|
||||
|
||||
if (sort_column >= 0 && sort_column < GameListModel::Column_Count)
|
||||
{
|
||||
Host::SetBaseStringSettingValue(
|
||||
"GameListTableView", "SortColumn", GameListModel::getColumnName(static_cast<GameListModel::Column>(sort_column)));
|
||||
}
|
||||
|
||||
Host::SetBaseBoolSettingValue("GameListTableView", "SortDescending", sort_descending);
|
||||
Host::CommitBaseSettingChanges();
|
||||
}
|
||||
|
||||
const GameList::Entry* GameListWidget::getSelectedEntry() const
|
||||
{
|
||||
const GameList::Entry* entry;
|
||||
if (m_ui.stack->currentIndex() == 0)
|
||||
{
|
||||
const QItemSelectionModel* selection_model = m_table_view->selectionModel();
|
||||
if (!selection_model->hasSelection())
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
const QModelIndexList selected_rows = selection_model->selectedRows();
|
||||
if (selected_rows.empty())
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
const QModelIndex source_index = m_sort_model->mapToSource(selected_rows[0]);
|
||||
if (!source_index.isValid())
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
return GameList::GetEntryByIndex(source_index.row());
|
||||
entry = GameList::GetEntryByIndex(source_index.row());
|
||||
}
|
||||
else
|
||||
{
|
||||
const QItemSelectionModel* selection_model = m_list_view->selectionModel();
|
||||
if (!selection_model->hasSelection())
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
const QModelIndex source_index = m_sort_model->mapToSource(selection_model->currentIndex());
|
||||
if (!source_index.isValid())
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
return GameList::GetEntryByIndex(source_index.row());
|
||||
entry = GameList::GetEntryByIndex(source_index.row());
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
return std::nullopt;
|
||||
|
||||
// Copy the entry here instead of keeping the lock held to avoid deadlocks.
|
||||
return *entry;
|
||||
}
|
||||
|
||||
void GameListWidget::rescanFile(const std::string& path)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "QtUtils.h"
|
||||
#include "ui_EmptyGameListWidget.h"
|
||||
#include "ui_GameListWidget.h"
|
||||
|
||||
@@ -46,18 +47,18 @@ public:
|
||||
void initialize();
|
||||
void resizeTableViewColumnsToFit();
|
||||
|
||||
void refresh(bool invalidate_cache);
|
||||
void refresh(bool invalidate_cache, bool popup_on_error);
|
||||
void cancelRefresh();
|
||||
void reloadThemeSpecificImages();
|
||||
void setCustomBackground(bool force = false);
|
||||
void updateCustomBackgroundState(bool force_start = false);
|
||||
void processBackgroundFrames(bool fill_area);
|
||||
void setCustomBackground();
|
||||
void updateCustomBackgroundState(const bool force_start = false);
|
||||
void processBackgroundFrames();
|
||||
|
||||
bool isShowingGameList() const;
|
||||
bool isShowingGameGrid() const;
|
||||
bool getShowGridCoverTitles() const;
|
||||
|
||||
const GameList::Entry* getSelectedEntry() const;
|
||||
std::optional<GameList::Entry> getSelectedEntry() const;
|
||||
|
||||
/// Rescans a single file. NOTE: Happens on UI thread.
|
||||
void rescanFile(const std::string& path);
|
||||
@@ -81,10 +82,10 @@ private Q_SLOTS:
|
||||
void onTableViewItemActivated(const QModelIndex& index);
|
||||
void onTableViewContextMenuRequested(const QPoint& point);
|
||||
void onTableViewHeaderContextMenuRequested(const QPoint& point);
|
||||
void onTableViewHeaderSortIndicatorChanged(int, Qt::SortOrder);
|
||||
void onListViewItemActivated(const QModelIndex& index);
|
||||
void onListViewContextMenuRequested(const QPoint& point);
|
||||
void onCoverScaleChanged();
|
||||
void onTableHeaderStateChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
void showGameList();
|
||||
@@ -102,11 +103,10 @@ protected:
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void loadTableViewColumnVisibilitySettings();
|
||||
void saveTableViewColumnVisibilitySettings();
|
||||
void saveTableViewColumnVisibilitySettings(int column);
|
||||
void loadTableViewColumnSortSettings();
|
||||
void saveTableViewColumnSortSettings();
|
||||
void loadTableHeaderState();
|
||||
void applyTableHeaderDefaults();
|
||||
void resetTableHeaderToDefault();
|
||||
void saveSortSettings(int column, Qt::SortOrder sort_order);
|
||||
void listZoom(float delta);
|
||||
void updateToolbar();
|
||||
|
||||
@@ -123,4 +123,6 @@ private:
|
||||
GameListRefreshThread* m_refresh_thread = nullptr;
|
||||
|
||||
QMovie* m_background_movie = nullptr;
|
||||
QtUtils::ScalingMode m_background_scaling = QtUtils::ScalingMode::Fit;
|
||||
float m_background_opacity = 100.0f;
|
||||
};
|
||||
|
||||
@@ -214,6 +214,15 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>viewGameList</tabstop>
|
||||
<tabstop>viewGameGrid</tabstop>
|
||||
<tabstop>viewGridTitles</tabstop>
|
||||
<tabstop>gridScale</tabstop>
|
||||
<tabstop>filterType</tabstop>
|
||||
<tabstop>filterRegion</tabstop>
|
||||
<tabstop>searchText</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@
|
||||
class QProgressBar;
|
||||
|
||||
class AutoUpdaterDialog;
|
||||
class DisplayWidget;
|
||||
class DisplaySurface;
|
||||
class DisplayContainer;
|
||||
class GameListWidget;
|
||||
class ControllerSettingsWindow;
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
friend MainWindow;
|
||||
|
||||
QWidget* m_dialog_parent;
|
||||
bool m_has_lock;
|
||||
bool m_was_paused;
|
||||
bool m_was_fullscreen;
|
||||
};
|
||||
@@ -113,7 +114,7 @@ public:
|
||||
void checkMousePosition(int x, int y);
|
||||
public Q_SLOTS:
|
||||
void checkForUpdates(bool display_message, bool force_check);
|
||||
void refreshGameList(bool invalidate_cache);
|
||||
void refreshGameList(bool invalidate_cache, bool popup_on_error);
|
||||
void cancelGameListRefresh();
|
||||
void reportInfo(const QString& title, const QString& message);
|
||||
void reportError(const QString& title, const QString& message);
|
||||
@@ -170,6 +171,9 @@ private Q_SLOTS:
|
||||
void onAboutActionTriggered();
|
||||
void onToolsOpenDataDirectoryTriggered();
|
||||
void onToolsCoverDownloaderTriggered();
|
||||
#if !defined(__APPLE__)
|
||||
void onCreateGameShortcutTriggered();
|
||||
#endif
|
||||
void onToolsEditCheatsPatchesTriggered(bool cheats);
|
||||
void onCreateMemoryCardOpenRequested();
|
||||
void updateTheme();
|
||||
@@ -254,7 +258,6 @@ private:
|
||||
bool shouldAbortForMemcardBusy(const VMLock& lock);
|
||||
|
||||
QWidget* getContentParent();
|
||||
QWidget* getDisplayContainer() const;
|
||||
void saveDisplayWindowGeometryToConfig();
|
||||
void restoreDisplayWindowGeometryFromConfig();
|
||||
void createDisplayWidget(bool fullscreen, bool render_to_main);
|
||||
@@ -271,11 +274,11 @@ private:
|
||||
QString getDiscDevicePath(const QString& title);
|
||||
|
||||
void startGameListEntry(
|
||||
const GameList::Entry* entry, std::optional<s32> save_slot = std::nullopt, std::optional<bool> fast_boot = std::nullopt, bool load_backup = false);
|
||||
void setGameListEntryCoverImage(const GameList::Entry* entry);
|
||||
void clearGameListEntryPlayTime(const GameList::Entry* entry);
|
||||
void goToWikiPage(const GameList::Entry* entry);
|
||||
void openScreenshotsFolderForGame(const GameList::Entry* entry);
|
||||
const GameList::Entry& entry, std::optional<s32> save_slot = std::nullopt, std::optional<bool> fast_boot = std::nullopt, bool load_backup = false);
|
||||
void setGameListEntryCoverImage(const GameList::Entry& entry);
|
||||
void clearGameListEntryPlayTime(const GameList::Entry& entry, const time_t entry_played_time);
|
||||
void goToWikiPage(const GameList::Entry& entry);
|
||||
void openSnapshotsFolderForGame(const GameList::Entry& entry);
|
||||
|
||||
std::optional<bool> promptForResumeState(const QString& save_state_path);
|
||||
void loadSaveStateSlot(s32 slot, bool load_backup = false);
|
||||
@@ -288,8 +291,8 @@ private:
|
||||
Ui::MainWindow m_ui;
|
||||
|
||||
GameListWidget* m_game_list_widget = nullptr;
|
||||
DisplayWidget* m_display_widget = nullptr;
|
||||
DisplayContainer* m_display_container = nullptr;
|
||||
DisplaySurface* m_display_surface = nullptr;
|
||||
QWidget* m_display_container = nullptr;
|
||||
|
||||
SettingsWindow* m_settings_window = nullptr;
|
||||
ControllerSettingsWindow* m_controller_settings_window = nullptr;
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
<addaction name="actionDEV9Settings"/>
|
||||
<addaction name="actionFolderSettings"/>
|
||||
<addaction name="actionAchievementSettings"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionControllerSettings"/>
|
||||
<addaction name="actionHotkeySettings"/>
|
||||
<addaction name="separator"/>
|
||||
|
||||
@@ -88,12 +88,13 @@ static QTimer* s_settings_save_timer = nullptr;
|
||||
static std::unique_ptr<INISettingsInterface> s_base_settings_interface;
|
||||
static bool s_batch_mode = false;
|
||||
static bool s_nogui_mode = false;
|
||||
static bool s_start_fullscreen_ui = false;
|
||||
static bool s_start_fullscreen_ui_fullscreen = false;
|
||||
static bool s_start_big_picture_mode = false;
|
||||
static bool s_start_fullscreen = false;
|
||||
static bool s_test_config_and_exit = false;
|
||||
static bool s_run_setup_wizard = false;
|
||||
static bool s_cleanup_after_update = false;
|
||||
static bool s_boot_and_debug = false;
|
||||
static std::atomic_int s_vm_locked_with_dialog = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CPU Thread
|
||||
@@ -495,6 +496,11 @@ void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK: Prevent entering/exiting fullscreen mode when a dialog is shown, so
|
||||
// that we don't destroy the dialog while inside its exec function.
|
||||
if (s_vm_locked_with_dialog > 0)
|
||||
return;
|
||||
|
||||
if (!MTGS::IsOpen() || m_is_fullscreen == fullscreen)
|
||||
return;
|
||||
|
||||
@@ -764,12 +770,12 @@ void EmuThread::enumerateVibrationMotors()
|
||||
onVibrationMotorsEnumerated(qmotors);
|
||||
}
|
||||
|
||||
void EmuThread::connectDisplaySignals(DisplayWidget* widget)
|
||||
void EmuThread::connectDisplaySignals(DisplaySurface* widget)
|
||||
{
|
||||
widget->disconnect(this);
|
||||
|
||||
connect(widget, &DisplayWidget::windowResizedEvent, this, &EmuThread::onDisplayWindowResized);
|
||||
connect(widget, &DisplayWidget::windowRestoredEvent, this, &EmuThread::redrawDisplayWindow);
|
||||
connect(widget, &DisplaySurface::windowResizedEvent, this, &EmuThread::onDisplayWindowResized);
|
||||
connect(widget, &DisplaySurface::windowRestoredEvent, this, &EmuThread::redrawDisplayWindow);
|
||||
}
|
||||
|
||||
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
|
||||
@@ -959,6 +965,9 @@ void Host::OnGameChanged(const std::string& title, const std::string& elf_overri
|
||||
|
||||
void EmuThread::updatePerformanceMetrics(bool force)
|
||||
{
|
||||
if (!g_main_window)
|
||||
return;
|
||||
|
||||
if (VMManager::HasValidVM())
|
||||
{
|
||||
QString gs_stat;
|
||||
@@ -1152,7 +1161,7 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
|
||||
if (!filters.empty())
|
||||
{
|
||||
filters_str.append(QStringLiteral("All File Types (%1)")
|
||||
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||
for (const std::string& filter : filters)
|
||||
{
|
||||
filters_str.append(
|
||||
@@ -1713,6 +1722,16 @@ void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
|
||||
emit g_emu_thread->onMouseModeRequested(relative_mode, hide_cursor);
|
||||
}
|
||||
|
||||
void QtHost::LockVMWithDialog()
|
||||
{
|
||||
s_vm_locked_with_dialog++;
|
||||
}
|
||||
|
||||
void QtHost::UnlockVMWithDialog()
|
||||
{
|
||||
s_vm_locked_with_dialog--;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class QtHostProgressCallback final : public BaseProgressCallback
|
||||
@@ -2168,7 +2187,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
else if (CHECK_ARG(QStringLiteral("-fullscreen")))
|
||||
{
|
||||
AutoBoot(autoboot)->fullscreen = true;
|
||||
s_start_fullscreen_ui_fullscreen = true;
|
||||
s_start_fullscreen = true;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-nofullscreen")))
|
||||
@@ -2183,7 +2202,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-bigpicture")))
|
||||
{
|
||||
s_start_fullscreen_ui = true;
|
||||
s_start_big_picture_mode = true;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-testconfig")))
|
||||
@@ -2244,7 +2263,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
|
||||
// if we don't have autoboot, we definitely don't want batch mode (because that'll skip
|
||||
// scanning the game list).
|
||||
if (s_batch_mode && !s_start_fullscreen_ui && !autoboot)
|
||||
if (s_batch_mode && !s_start_big_picture_mode && !autoboot)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QStringLiteral("Error"),
|
||||
s_nogui_mode ? QStringLiteral("Cannot use no-gui mode, because no boot filename was specified.") :
|
||||
@@ -2328,7 +2347,12 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
CrashHandler::Install();
|
||||
|
||||
// Exceptions are disabled, so we can't try/catch this.
|
||||
// Timestamps in some locales showed up wrong on Windows.
|
||||
// Qt already applies the user locale on Unix-like systems.
|
||||
#ifdef _WIN32
|
||||
std::locale::global(std::locale(""));
|
||||
#endif
|
||||
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
QtHost::RegisterTypes();
|
||||
@@ -2380,7 +2404,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// When running in batch mode, ensure game list is loaded, but don't scan for any new files.
|
||||
if (!s_batch_mode)
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, false);
|
||||
else
|
||||
GameList::Refresh(false, true);
|
||||
|
||||
@@ -2393,8 +2417,9 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// Initialize big picture mode if requested by command line or settings.
|
||||
if (s_start_fullscreen_ui || Host::GetBaseBoolSettingValue("UI", "StartBigPictureMode", false))
|
||||
g_emu_thread->startFullscreenUI(s_start_fullscreen_ui_fullscreen);
|
||||
// As CLI arguments are baked-in, they're tracked separately from settings which can be changed during runtime.
|
||||
if (s_start_big_picture_mode || Host::GetBaseBoolSettingValue("UI", "StartBigPictureMode", false))
|
||||
g_emu_thread->startFullscreenUI(s_start_fullscreen || Host::GetBaseBoolSettingValue("UI", "StartFullscreen", false));
|
||||
|
||||
if (s_boot_and_debug || DebuggerWindow::shouldShowOnStartup())
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
class SettingsInterface;
|
||||
|
||||
class DisplayWidget;
|
||||
class DisplaySurface;
|
||||
struct VMBootParameters;
|
||||
|
||||
enum class CDVD_SourceType : uint8_t;
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
|
||||
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
|
||||
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window);
|
||||
void connectDisplaySignals(DisplayWidget* widget);
|
||||
void connectDisplaySignals(DisplaySurface* widget);
|
||||
void releaseRenderWindow();
|
||||
|
||||
void startBackgroundControllerPollTimer();
|
||||
@@ -290,4 +290,10 @@ namespace QtHost
|
||||
|
||||
/// Compare strings in the locale of the current UI language
|
||||
int LocaleSensitiveCompare(QStringView lhs, QStringView rhs);
|
||||
|
||||
/// Determines whether or not requests to enter/exit fullscreen mode should
|
||||
/// be ignored. This is a hack so that we don't destroy a dialog box while
|
||||
/// inside its exec function, which would cause a crash.
|
||||
void LockVMWithDialog();
|
||||
void UnlockVMWithDialog();
|
||||
} // namespace QtHost
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QHeaderView>
|
||||
@@ -40,8 +39,6 @@
|
||||
#if defined(_WIN32)
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include <Shlobj.h>
|
||||
#elif !defined(APPLE)
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
|
||||
namespace QtUtils
|
||||
@@ -90,7 +87,9 @@ namespace QtUtils
|
||||
|
||||
const int min_column_width = header->minimumSectionSize();
|
||||
const int scrollbar_width = ((view->verticalScrollBar() && view->verticalScrollBar()->isVisible()) ||
|
||||
view->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOn) ? view->verticalScrollBar()->width() : 0;
|
||||
view->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOn) ?
|
||||
view->verticalScrollBar()->width() :
|
||||
0;
|
||||
int num_flex_items = 0;
|
||||
int total_width = 0;
|
||||
int column_index = 0;
|
||||
@@ -137,6 +136,126 @@ namespace QtUtils
|
||||
ResizeColumnsForView(view, widths);
|
||||
}
|
||||
|
||||
void resizeAndScalePixmap(QPixmap* pm, const int expected_width, const int expected_height, const qreal dpr, const ScalingMode scaling_mode, const float opacity)
|
||||
{
|
||||
if (!pm || pm->isNull() || pm->width() <= 0 || pm->height() <= 0)
|
||||
return;
|
||||
|
||||
const int dpr_expected_width = qRound(expected_width * dpr);
|
||||
const int dpr_expected_height = qRound(expected_height * dpr);
|
||||
|
||||
if (pm->width() == dpr_expected_width &&
|
||||
pm->height() == dpr_expected_height &&
|
||||
pm->devicePixelRatio() == dpr &&
|
||||
opacity == 100.0f)
|
||||
{
|
||||
switch (scaling_mode)
|
||||
{
|
||||
case ScalingMode::Fit:
|
||||
case ScalingMode::Stretch:
|
||||
case ScalingMode::Center:
|
||||
return;
|
||||
|
||||
case ScalingMode::Fill:
|
||||
case ScalingMode::Tile:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap final_pixmap(dpr_expected_width, dpr_expected_height);
|
||||
final_pixmap.setDevicePixelRatio(dpr);
|
||||
final_pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter;
|
||||
painter.begin(&final_pixmap);
|
||||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
painter.setOpacity(opacity / 100.0f);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
|
||||
const QRectF srcRect(0, 0, pm->width(), pm->height());
|
||||
const QRectF painterRect(0, 0, expected_width, expected_height);
|
||||
|
||||
switch (scaling_mode)
|
||||
{
|
||||
case ScalingMode::Fit:
|
||||
case ScalingMode::Fill:
|
||||
{
|
||||
auto const aspect_mode = (scaling_mode == ScalingMode::Fit) ?
|
||||
Qt::KeepAspectRatio :
|
||||
Qt::KeepAspectRatioByExpanding;
|
||||
|
||||
QSizeF scaledSize(pm->width(), pm->height());
|
||||
scaledSize.scale(dpr_expected_width, dpr_expected_height, aspect_mode);
|
||||
|
||||
*pm = pm->scaled(
|
||||
qRound(scaledSize.width()),
|
||||
qRound(scaledSize.height()),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation
|
||||
);
|
||||
|
||||
const QRectF scaledSrcRect(0, 0, pm->width(), pm->height());
|
||||
|
||||
QSizeF logicalSize = pm->size() / dpr;
|
||||
QRectF destRect(QPointF(0, 0), logicalSize);
|
||||
|
||||
destRect.moveCenter(painterRect.center());
|
||||
|
||||
painter.drawPixmap(destRect, *pm, scaledSrcRect);
|
||||
break;
|
||||
}
|
||||
case ScalingMode::Stretch:
|
||||
{
|
||||
*pm = pm->scaled(
|
||||
dpr_expected_width,
|
||||
dpr_expected_height,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation
|
||||
);
|
||||
|
||||
const QRectF scaledSrcRect(0, 0, pm->width(), pm->height());
|
||||
|
||||
painter.drawPixmap(painterRect, *pm, scaledSrcRect);
|
||||
break;
|
||||
}
|
||||
case ScalingMode::Center:
|
||||
{
|
||||
const qreal pmWidth = pm->width() / dpr;
|
||||
const qreal pmHeight = pm->height() / dpr;
|
||||
|
||||
QRectF destRect(0, 0, pmWidth, pmHeight);
|
||||
|
||||
destRect.moveCenter(painterRect.center());
|
||||
|
||||
painter.drawPixmap(destRect, *pm, srcRect);
|
||||
break;
|
||||
}
|
||||
case ScalingMode::Tile:
|
||||
{
|
||||
const qreal tileWidth = pm->width() / dpr;
|
||||
const qreal tileHeight = pm->height() / dpr;
|
||||
|
||||
if (tileWidth <= 0 || tileHeight <= 0)
|
||||
break;
|
||||
|
||||
QPixmap tileSource = pm->scaled(tileWidth, tileHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
tileSource.setDevicePixelRatio(dpr);
|
||||
|
||||
QBrush tileBrush(tileSource);
|
||||
tileBrush.setTextureImage(tileSource.toImage());
|
||||
|
||||
painter.fillRect(painterRect, tileBrush);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
painter.end();
|
||||
*pm = std::move(final_pixmap);
|
||||
}
|
||||
|
||||
void ShowInFileExplorer(QWidget* parent, const QFileInfo& file)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
@@ -252,68 +371,6 @@ namespace QtUtils
|
||||
widget->resize(width, height);
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget)
|
||||
{
|
||||
WindowInfo wi;
|
||||
|
||||
// Windows and Apple are easy here since there's no display connection.
|
||||
#if defined(_WIN32)
|
||||
wi.type = WindowInfo::Type::Win32;
|
||||
wi.window_handle = reinterpret_cast<void*>(widget->winId());
|
||||
#elif defined(__APPLE__)
|
||||
wi.type = WindowInfo::Type::MacOS;
|
||||
wi.window_handle = reinterpret_cast<void*>(widget->winId());
|
||||
#else
|
||||
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
||||
const QString platform_name = QGuiApplication::platformName();
|
||||
if (platform_name == QStringLiteral("xcb"))
|
||||
{
|
||||
// Can't get a handle for an unmapped window in X, it doesn't like it.
|
||||
if (!widget->isVisible())
|
||||
{
|
||||
Console.WriteLn("Returning null window info for widget because it is not visible.");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
wi.type = WindowInfo::Type::X11;
|
||||
wi.display_connection = pni->nativeResourceForWindow("display", widget->windowHandle());
|
||||
wi.window_handle = reinterpret_cast<void*>(widget->winId());
|
||||
}
|
||||
else if (platform_name == QStringLiteral("wayland"))
|
||||
{
|
||||
wi.type = WindowInfo::Type::Wayland;
|
||||
wi.display_connection = pni->nativeResourceForWindow("display", widget->windowHandle());
|
||||
wi.window_handle = pni->nativeResourceForWindow("surface", widget->windowHandle());
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn("Unknown PNI platform '%s'.", platform_name.toUtf8().constData());
|
||||
return std::nullopt;
|
||||
}
|
||||
#endif
|
||||
|
||||
const qreal dpr = widget->devicePixelRatioF();
|
||||
wi.surface_width = static_cast<u32>(static_cast<qreal>(widget->width()) * dpr);
|
||||
wi.surface_height = static_cast<u32>(static_cast<qreal>(widget->height()) * dpr);
|
||||
wi.surface_scale = static_cast<float>(dpr);
|
||||
|
||||
// Query refresh rate, we need it for sync.
|
||||
std::optional<float> surface_refresh_rate = WindowInfo::QueryRefreshRateForWindow(wi);
|
||||
if (!surface_refresh_rate.has_value())
|
||||
{
|
||||
// Fallback to using the screen, getting the rate for Wayland is an utter mess otherwise.
|
||||
const QScreen* widget_screen = widget->screen();
|
||||
if (!widget_screen)
|
||||
widget_screen = QGuiApplication::primaryScreen();
|
||||
surface_refresh_rate = widget_screen ? static_cast<float>(widget_screen->refreshRate()) : 0.0f;
|
||||
}
|
||||
|
||||
wi.surface_refresh_rate = surface_refresh_rate.value();
|
||||
INFO_LOG("Surface refresh rate: {} hz", wi.surface_refresh_rate);
|
||||
|
||||
return wi;
|
||||
}
|
||||
|
||||
QString AbstractItemModelToCSV(QAbstractItemModel* model, int role, bool useQuotes)
|
||||
{
|
||||
QString csv;
|
||||
@@ -346,11 +403,6 @@ namespace QtUtils
|
||||
return csv;
|
||||
}
|
||||
|
||||
bool IsLightTheme(const QPalette& palette)
|
||||
{
|
||||
return palette.text().color().lightnessF() < 0.5;
|
||||
}
|
||||
|
||||
bool IsCompositorManagerRunning()
|
||||
{
|
||||
if (qEnvironmentVariableIsSet("PCSX2_NO_COMPOSITING"))
|
||||
|
||||
@@ -9,11 +9,20 @@
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QWindow>
|
||||
#if !defined(_WIN32) and !defined(__APPLE__)
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
#include <QtGui/QScreen>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
|
||||
#include "common/Console.h"
|
||||
|
||||
class ByteStream;
|
||||
|
||||
class QAction;
|
||||
@@ -49,6 +58,20 @@ namespace QtUtils
|
||||
void ResizeColumnsForTableView(QTableView* view, const std::initializer_list<int>& widths);
|
||||
void ResizeColumnsForTreeView(QTreeView* view, const std::initializer_list<int>& widths);
|
||||
|
||||
enum struct ScalingMode
|
||||
{
|
||||
Fit,
|
||||
Fill,
|
||||
Stretch,
|
||||
Center,
|
||||
Tile,
|
||||
|
||||
MaxCount
|
||||
};
|
||||
|
||||
/// Resize and scale a given Pixmap (and optionally adjust opacity)
|
||||
void resizeAndScalePixmap(QPixmap* pm, const int expected_width, const int expected_height, const qreal dpr, const ScalingMode scaling_mode, const float opacity);
|
||||
|
||||
/// Returns a key id for a key event, including any modifiers that we need (e.g. Keypad).
|
||||
/// NOTE: Defined in QtKeyCodes.cpp, not QtUtils.cpp.
|
||||
u32 KeyEventToCode(const QKeyEvent* ev);
|
||||
@@ -83,8 +106,82 @@ namespace QtUtils
|
||||
/// Adjusts the fixed size for a window if it's not resizeable.
|
||||
void ResizePotentiallyFixedSizeWindow(QWidget* widget, int width, int height);
|
||||
|
||||
/// Returns the common window info structure for a Qt widget.
|
||||
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget);
|
||||
/// Returns the common window info structure for a Qt Window/Widget.
|
||||
template <class T>
|
||||
requires std::is_base_of_v<QWidget, T> || std::is_base_of_v<QWindow, T>
|
||||
std::optional<WindowInfo> GetWindowInfoForWindow(T* window)
|
||||
{
|
||||
WindowInfo wi;
|
||||
|
||||
// Windows and Apple are easy here since there's no display connection.
|
||||
#if defined(_WIN32)
|
||||
wi.type = WindowInfo::Type::Win32;
|
||||
wi.window_handle = reinterpret_cast<void*>(window->winId());
|
||||
#elif defined(__APPLE__)
|
||||
wi.type = WindowInfo::Type::MacOS;
|
||||
wi.window_handle = reinterpret_cast<void*>(window->winId());
|
||||
#else
|
||||
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
||||
const QString platform_name = QGuiApplication::platformName();
|
||||
|
||||
QWindow* windowHandle;
|
||||
if constexpr (std::is_base_of_v<QWidget, T>)
|
||||
windowHandle = window->windowHandle();
|
||||
else
|
||||
windowHandle = window;
|
||||
|
||||
if (platform_name == QStringLiteral("xcb"))
|
||||
{
|
||||
// Can't get a handle for an unmapped window in X, it doesn't like it.
|
||||
if (!window->isVisible())
|
||||
{
|
||||
Console.WriteLn("Returning null window info for widget because it is not visible.");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
wi.type = WindowInfo::Type::X11;
|
||||
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle);
|
||||
wi.window_handle = reinterpret_cast<void*>(window->winId());
|
||||
}
|
||||
else if (platform_name == QStringLiteral("wayland"))
|
||||
{
|
||||
wi.type = WindowInfo::Type::Wayland;
|
||||
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle);
|
||||
wi.window_handle = pni->nativeResourceForWindow("surface", windowHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn("Unknown PNI platform '%s'.", platform_name.toUtf8().constData());
|
||||
return std::nullopt;
|
||||
}
|
||||
#endif
|
||||
|
||||
qreal dpr;
|
||||
if constexpr (std::is_base_of_v<QWidget, T>)
|
||||
dpr = window->devicePixelRatioF();
|
||||
else
|
||||
dpr = window->devicePixelRatio();
|
||||
|
||||
wi.surface_width = static_cast<u32>(std::max(static_cast<int>(std::round(static_cast<qreal>(window->width()) * dpr)), 1));
|
||||
wi.surface_height = static_cast<u32>(std::max(static_cast<int>(std::round(static_cast<qreal>(window->height()) * dpr)), 1));
|
||||
wi.surface_scale = static_cast<float>(dpr);
|
||||
|
||||
// Query refresh rate, we need it for sync.
|
||||
std::optional<float> surface_refresh_rate = WindowInfo::QueryRefreshRateForWindow(wi);
|
||||
if (!surface_refresh_rate.has_value())
|
||||
{
|
||||
// Fallback to using the screen, getting the rate for Wayland is an utter mess otherwise.
|
||||
const QScreen* widget_screen = window->screen();
|
||||
if (!widget_screen)
|
||||
widget_screen = QGuiApplication::primaryScreen();
|
||||
surface_refresh_rate = widget_screen ? static_cast<float>(widget_screen->refreshRate()) : 0.0f;
|
||||
}
|
||||
|
||||
wi.surface_refresh_rate = surface_refresh_rate.value();
|
||||
INFO_LOG("Surface refresh rate: {} hz", wi.surface_refresh_rate);
|
||||
|
||||
return wi;
|
||||
}
|
||||
|
||||
/// Converts a value to a QString of said value with a proper fixed width
|
||||
template <typename T>
|
||||
@@ -96,9 +193,7 @@ namespace QtUtils
|
||||
/// Converts an abstract item model to a CSV string.
|
||||
QString AbstractItemModelToCSV(QAbstractItemModel* model, int role = Qt::DisplayRole, bool useQuotes = false);
|
||||
|
||||
// Heuristic to check if the current theme is a light or dark theme.
|
||||
bool IsLightTheme(const QPalette& palette);
|
||||
|
||||
/// Checks if we can use transparency effects e.g. for dock drop indicators.
|
||||
bool IsCompositorManagerRunning();
|
||||
|
||||
/// Sets the scalable icon to a given label (svg icons, or icons with multiple size pixmaps)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<class>AchievementLoginDialog</class>
|
||||
<widget class="QDialog" name="AchievementLoginDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
<enum>Qt::WindowModality::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -44,7 +44,7 @@
|
||||
<string comment="Header text">RetroAchievements Login</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -63,7 +63,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -80,6 +80,9 @@
|
||||
<property name="text">
|
||||
<string>User Name:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>userName</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -90,12 +93,15 @@
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>password</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
<enum>QLineEdit::EchoMode::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -113,7 +119,7 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -121,6 +127,10 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>userName</tabstop>
|
||||
<tabstop>password</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -78,13 +78,13 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
<enum>QSlider::TickPosition::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
@@ -124,13 +124,13 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
<enum>QSlider::TickPosition::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
@@ -165,6 +165,9 @@
|
||||
<property name="text">
|
||||
<string>Notification Position:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>notificationPosition</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
@@ -284,6 +287,9 @@
|
||||
<property name="text">
|
||||
<string>Overlay Position:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>overlayPosition</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
@@ -418,7 +424,13 @@
|
||||
Login token generated at:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>viewProfile</cstring>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -458,7 +470,10 @@ Login token generated at:</string>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="gameInfo">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -471,7 +486,7 @@ Login token generated at:</string>
|
||||
<string><html><head/><body><p align="justify">PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at <a href="https://retroachievements.org/">retroachievements.org</a>.</p><p align="justify">To view the achievement list in-game, press the hotkey for <span style=" font-weight:600;">Open Pause Menu</span> and select <span style=" font-weight:600;">Achievements</span> from the menu.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
<enum>Qt::TextFormat::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -487,7 +502,7 @@ Login token generated at:</string>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -499,6 +514,39 @@ Login token generated at:</string>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>enable</tabstop>
|
||||
<tabstop>hardcoreMode</tabstop>
|
||||
<tabstop>encoreMode</tabstop>
|
||||
<tabstop>spectatorMode</tabstop>
|
||||
<tabstop>unofficialAchievements</tabstop>
|
||||
<tabstop>achievementNotifications</tabstop>
|
||||
<tabstop>achievementNotificationsDuration</tabstop>
|
||||
<tabstop>leaderboardNotifications</tabstop>
|
||||
<tabstop>leaderboardNotificationsDuration</tabstop>
|
||||
<tabstop>soundEffects</tabstop>
|
||||
<tabstop>notificationPosition</tabstop>
|
||||
<tabstop>overlays</tabstop>
|
||||
<tabstop>leaderboardOverlays</tabstop>
|
||||
<tabstop>overlayPosition</tabstop>
|
||||
<tabstop>notificationSound</tabstop>
|
||||
<tabstop>notificationSoundPath</tabstop>
|
||||
<tabstop>notificationSoundBrowse</tabstop>
|
||||
<tabstop>notificationSoundOpen</tabstop>
|
||||
<tabstop>notificationSoundReset</tabstop>
|
||||
<tabstop>unlockSound</tabstop>
|
||||
<tabstop>unlockSoundPath</tabstop>
|
||||
<tabstop>unlockSoundBrowse</tabstop>
|
||||
<tabstop>unlockSoundOpen</tabstop>
|
||||
<tabstop>unlockSoundReset</tabstop>
|
||||
<tabstop>lbSound</tabstop>
|
||||
<tabstop>lbSoundPath</tabstop>
|
||||
<tabstop>lbSoundBrowse</tabstop>
|
||||
<tabstop>lbSoundOpen</tabstop>
|
||||
<tabstop>lbSoundReset</tabstop>
|
||||
<tabstop>viewProfile</tabstop>
|
||||
<tabstop>loginButton</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
<property name="text">
|
||||
<string extracomment="Rounding refers here to the mathematical term.">Rounding Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>eeRoundingMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -63,6 +66,9 @@
|
||||
<property name="text">
|
||||
<string extracomment="Rounding refers here to the mathematical term.">Division Rounding Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>eeDivRoundingMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -94,6 +100,9 @@
|
||||
<property name="text">
|
||||
<string extracomment="Clamping: Forcing out of bounds things in bounds by changing them to the closest possible value. In this case, this refers to clamping large PS2 floating point values (which map to infinity or NaN in PCs' IEEE754 floats) to non-infinite ones.">Clamping Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>eeClampMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -187,6 +196,9 @@
|
||||
<property name="text">
|
||||
<string>VU1 Rounding Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>vu1RoundingMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -274,6 +286,9 @@
|
||||
<property name="text">
|
||||
<string>VU0 Clamping Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>vu0ClampMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
@@ -281,6 +296,9 @@
|
||||
<property name="text">
|
||||
<string>VU0 Rounding Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>vu0RoundingMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
@@ -288,6 +306,9 @@
|
||||
<property name="text">
|
||||
<string>VU1 Clamping Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>vu1ClampMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -446,6 +467,9 @@
|
||||
<property name="text">
|
||||
<string>Compression Level:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>savestateCompressionLevel</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
@@ -460,6 +484,9 @@
|
||||
<property name="text">
|
||||
<string>Compression Method:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>savestateCompressionMethod</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
@@ -499,6 +526,9 @@
|
||||
<property name="text">
|
||||
<string>Slot:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pineSlot</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
@@ -514,7 +544,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -526,6 +556,36 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>eeRoundingMode</tabstop>
|
||||
<tabstop>eeDivRoundingMode</tabstop>
|
||||
<tabstop>eeClampMode</tabstop>
|
||||
<tabstop>eeRecompiler</tabstop>
|
||||
<tabstop>eeCache</tabstop>
|
||||
<tabstop>eeWaitLoopDetection</tabstop>
|
||||
<tabstop>eeINTCSpinDetection</tabstop>
|
||||
<tabstop>eeFastmem</tabstop>
|
||||
<tabstop>pauseOnTLBMiss</tabstop>
|
||||
<tabstop>extraMemory</tabstop>
|
||||
<tabstop>vu0RoundingMode</tabstop>
|
||||
<tabstop>vu0ClampMode</tabstop>
|
||||
<tabstop>vu1RoundingMode</tabstop>
|
||||
<tabstop>vu1ClampMode</tabstop>
|
||||
<tabstop>vu0Recompiler</tabstop>
|
||||
<tabstop>vu1Recompiler</tabstop>
|
||||
<tabstop>vuFlagHack</tabstop>
|
||||
<tabstop>instantVU1</tabstop>
|
||||
<tabstop>iopRecompiler</tabstop>
|
||||
<tabstop>gameFixes</tabstop>
|
||||
<tabstop>patches</tabstop>
|
||||
<tabstop>savestateCompressionMethod</tabstop>
|
||||
<tabstop>savestateCompressionLevel</tabstop>
|
||||
<tabstop>backupSaveStates</tabstop>
|
||||
<tabstop>saveStateOnShutdown</tabstop>
|
||||
<tabstop>savestateSelector</tabstop>
|
||||
<tabstop>pineEnable</tabstop>
|
||||
<tabstop>pineSlot</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<property name="text">
|
||||
<string>Circular Wrap:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>circularWrap</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -59,6 +62,9 @@
|
||||
<property name="text">
|
||||
<string>Shift:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>shift</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
@@ -99,6 +105,9 @@
|
||||
<property name="text">
|
||||
<string>Depth:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>depth</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
@@ -139,6 +148,9 @@
|
||||
<property name="text">
|
||||
<string>Focus:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>focus</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
@@ -179,6 +191,9 @@
|
||||
<property name="text">
|
||||
<string>Center Image:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>centerImage</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
@@ -219,6 +234,9 @@
|
||||
<property name="text">
|
||||
<string>Front Separation:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>frontSeparation</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
@@ -259,6 +277,9 @@
|
||||
<property name="text">
|
||||
<string>Rear Separation:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>rearSeparation</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
@@ -299,6 +320,9 @@
|
||||
<property name="text">
|
||||
<string>Low Cutoff:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>lowCutoff</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
@@ -339,6 +363,9 @@
|
||||
<property name="text">
|
||||
<string>High Cutoff:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>highCutoff</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
@@ -428,6 +455,9 @@
|
||||
<property name="text">
|
||||
<string>Block Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>blockSize</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -471,6 +501,18 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>blockSize</tabstop>
|
||||
<tabstop>circularWrap</tabstop>
|
||||
<tabstop>shift</tabstop>
|
||||
<tabstop>depth</tabstop>
|
||||
<tabstop>focus</tabstop>
|
||||
<tabstop>centerImage</tabstop>
|
||||
<tabstop>frontSeparation</tabstop>
|
||||
<tabstop>rearSeparation</tabstop>
|
||||
<tabstop>lowCutoff</tabstop>
|
||||
<tabstop>highCutoff</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<property name="text">
|
||||
<string>Driver:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>driver</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -76,10 +79,10 @@
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBothSides</enum>
|
||||
<enum>QSlider::TickPosition::TicksBothSides</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>20</number>
|
||||
@@ -117,6 +120,9 @@
|
||||
<property name="text">
|
||||
<string>Buffer Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>bufferMS</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
@@ -125,7 +131,10 @@
|
||||
<string>Maximum latency: 0 frames (0.00ms)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -134,6 +143,9 @@
|
||||
<property name="text">
|
||||
<string>Backend:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>audioBackend</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
@@ -147,10 +159,10 @@
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBothSides</enum>
|
||||
<enum>QSlider::TickPosition::TicksBothSides</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>20</number>
|
||||
@@ -181,6 +193,9 @@
|
||||
<property name="text">
|
||||
<string>Output Latency:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>outputLatencyMS</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -191,6 +206,9 @@
|
||||
<property name="text">
|
||||
<string>Output Device:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>outputDevice</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
@@ -198,6 +216,9 @@
|
||||
<property name="text">
|
||||
<string>Expansion:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>expansionMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
@@ -205,6 +226,9 @@
|
||||
<property name="text">
|
||||
<string>Synchronization:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>syncMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -221,6 +245,9 @@
|
||||
<property name="text">
|
||||
<string>Standard Volume:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>standardVolume</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -234,10 +261,10 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBothSides</enum>
|
||||
<enum>QSlider::TickPosition::TicksBothSides</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
@@ -256,7 +283,7 @@
|
||||
<string>100%</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -283,10 +310,10 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBothSides</enum>
|
||||
<enum>QSlider::TickPosition::TicksBothSides</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
@@ -305,7 +332,7 @@
|
||||
<string>100%</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -326,6 +353,9 @@
|
||||
<property name="text">
|
||||
<string>Fast Forward Volume:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>fastForwardVolume</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@@ -341,7 +371,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -353,6 +383,23 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>audioBackend</tabstop>
|
||||
<tabstop>driver</tabstop>
|
||||
<tabstop>outputDevice</tabstop>
|
||||
<tabstop>expansionMode</tabstop>
|
||||
<tabstop>expansionSettings</tabstop>
|
||||
<tabstop>syncMode</tabstop>
|
||||
<tabstop>stretchSettings</tabstop>
|
||||
<tabstop>bufferMS</tabstop>
|
||||
<tabstop>outputLatencyMS</tabstop>
|
||||
<tabstop>outputLatencyMinimal</tabstop>
|
||||
<tabstop>standardVolume</tabstop>
|
||||
<tabstop>resetStandardVolume</tabstop>
|
||||
<tabstop>fastForwardVolume</tabstop>
|
||||
<tabstop>resetFastForwardVolume</tabstop>
|
||||
<tabstop>muted</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<property name="text">
|
||||
<string>Sequence Length:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>sequenceLength</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -59,6 +62,9 @@
|
||||
<property name="text">
|
||||
<string>Seekwindow Size:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>seekWindowSize</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -99,6 +105,9 @@
|
||||
<property name="text">
|
||||
<string>Overlap:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>overlap</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
@@ -199,6 +208,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>sequenceLength</tabstop>
|
||||
<tabstop>seekWindowSize</tabstop>
|
||||
<tabstop>overlap</tabstop>
|
||||
<tabstop>useQuickSeek</tabstop>
|
||||
<tabstop>useAAFilter</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>searchDirectory</cstring>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
@@ -74,7 +80,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -156,7 +162,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -168,6 +174,16 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>searchDirectory</tabstop>
|
||||
<tabstop>browseSearchDirectory</tabstop>
|
||||
<tabstop>resetSearchDirectory</tabstop>
|
||||
<tabstop>fileList</tabstop>
|
||||
<tabstop>openSearchDirectory</tabstop>
|
||||
<tabstop>refresh</tabstop>
|
||||
<tabstop>fastBoot</tabstop>
|
||||
<tabstop>fastBootFastForward</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1021,7 +1021,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1038,7 +1038,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1076,7 +1076,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1093,7 +1093,7 @@
|
||||
<item row="2" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -1255,6 +1255,36 @@
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>Up</tabstop>
|
||||
<tabstop>Down</tabstop>
|
||||
<tabstop>Left</tabstop>
|
||||
<tabstop>Right</tabstop>
|
||||
<tabstop>Triangle</tabstop>
|
||||
<tabstop>Cross</tabstop>
|
||||
<tabstop>Square</tabstop>
|
||||
<tabstop>Circle</tabstop>
|
||||
<tabstop>L1</tabstop>
|
||||
<tabstop>L2</tabstop>
|
||||
<tabstop>R1</tabstop>
|
||||
<tabstop>R2</tabstop>
|
||||
<tabstop>LUp</tabstop>
|
||||
<tabstop>LDown</tabstop>
|
||||
<tabstop>LLeft</tabstop>
|
||||
<tabstop>LRight</tabstop>
|
||||
<tabstop>L3</tabstop>
|
||||
<tabstop>RUp</tabstop>
|
||||
<tabstop>RDown</tabstop>
|
||||
<tabstop>RLeft</tabstop>
|
||||
<tabstop>RRight</tabstop>
|
||||
<tabstop>R3</tabstop>
|
||||
<tabstop>Select</tabstop>
|
||||
<tabstop>Start</tabstop>
|
||||
<tabstop>Analog</tabstop>
|
||||
<tabstop>LargeMotor</tabstop>
|
||||
<tabstop>SmallMotor</tabstop>
|
||||
<tabstop>Pressure</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -55,7 +55,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -307,6 +307,19 @@
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>Start</tabstop>
|
||||
<tabstop>Select</tabstop>
|
||||
<tabstop>Up</tabstop>
|
||||
<tabstop>Down</tabstop>
|
||||
<tabstop>Orange</tabstop>
|
||||
<tabstop>Blue</tabstop>
|
||||
<tabstop>Yellow</tabstop>
|
||||
<tabstop>Red</tabstop>
|
||||
<tabstop>Green</tabstop>
|
||||
<tabstop>Whammy</tabstop>
|
||||
<tabstop>Tilt</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -683,7 +683,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -700,7 +700,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -738,7 +738,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -799,7 +799,7 @@
|
||||
<item row="1" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -825,6 +825,26 @@
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>Up</tabstop>
|
||||
<tabstop>Down</tabstop>
|
||||
<tabstop>Left</tabstop>
|
||||
<tabstop>Right</tabstop>
|
||||
<tabstop>Triangle</tabstop>
|
||||
<tabstop>Cross</tabstop>
|
||||
<tabstop>Square</tabstop>
|
||||
<tabstop>Circle</tabstop>
|
||||
<tabstop>L1</tabstop>
|
||||
<tabstop>L2</tabstop>
|
||||
<tabstop>R1</tabstop>
|
||||
<tabstop>R2</tabstop>
|
||||
<tabstop>DialLeft</tabstop>
|
||||
<tabstop>DialRight</tabstop>
|
||||
<tabstop>Select</tabstop>
|
||||
<tabstop>Start</tabstop>
|
||||
<tabstop>LargeMotor</tabstop>
|
||||
<tabstop>SmallMotor</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -581,7 +581,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -598,7 +598,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -636,7 +636,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -697,7 +697,7 @@
|
||||
<item row="1" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -723,6 +723,23 @@
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>Up</tabstop>
|
||||
<tabstop>Down</tabstop>
|
||||
<tabstop>Left</tabstop>
|
||||
<tabstop>Right</tabstop>
|
||||
<tabstop>I</tabstop>
|
||||
<tabstop>II</tabstop>
|
||||
<tabstop>A</tabstop>
|
||||
<tabstop>B</tabstop>
|
||||
<tabstop>L</tabstop>
|
||||
<tabstop>R</tabstop>
|
||||
<tabstop>TwistLeft</tabstop>
|
||||
<tabstop>TwistRight</tabstop>
|
||||
<tabstop>Start</tabstop>
|
||||
<tabstop>LargeMotor</tabstop>
|
||||
<tabstop>SmallMotor</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -81,7 +81,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -343,7 +343,7 @@
|
||||
<item row="1" column="0" colspan="5">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -524,6 +524,19 @@
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>Select</tabstop>
|
||||
<tabstop>Start</tabstop>
|
||||
<tabstop>YellowL</tabstop>
|
||||
<tabstop>BlueL</tabstop>
|
||||
<tabstop>BlueR</tabstop>
|
||||
<tabstop>YellowR</tabstop>
|
||||
<tabstop>WhiteL</tabstop>
|
||||
<tabstop>GreenL</tabstop>
|
||||
<tabstop>Red</tabstop>
|
||||
<tabstop>GreenR</tabstop>
|
||||
<tabstop>WhiteR</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<item row="7" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -64,6 +64,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -90,6 +93,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -109,6 +115,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
@@ -142,6 +151,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -159,8 +171,7 @@
|
||||
<string>Controller LED Settings</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="lightbulb-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
<iconset theme="lightbulb-line"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -201,9 +212,15 @@
|
||||
<property name="text">
|
||||
<string>PCSX2 allows you to use your mouse to simulate analog stick movement.</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
@@ -241,6 +258,9 @@
|
||||
<property name="text">
|
||||
<string>The XInput source provides support for Xbox 360 / Xbox One / Xbox Series controllers, and third party controllers which implement the XInput protocol.</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -283,6 +303,22 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>enableSDLSource</tabstop>
|
||||
<tabstop>enableSDLEnhancedMode</tabstop>
|
||||
<tabstop>ledSettings</tabstop>
|
||||
<tabstop>enableSDLRawInput</tabstop>
|
||||
<tabstop>enableSDLIOKitDriver</tabstop>
|
||||
<tabstop>enableSDLMFIDriver</tabstop>
|
||||
<tabstop>enableXInputSource</tabstop>
|
||||
<tabstop>enableDInputSource</tabstop>
|
||||
<tabstop>enableMouseMapping</tabstop>
|
||||
<tabstop>mouseSettings</tabstop>
|
||||
<tabstop>multitapPort1</tabstop>
|
||||
<tabstop>multitapPort2</tabstop>
|
||||
<tabstop>useProfileHotkeyBindings</tabstop>
|
||||
<tabstop>deviceList</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<item row="3" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
@@ -92,7 +92,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<set>QDialogButtonBox::StandardButton::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -107,6 +107,13 @@
|
||||
<header>ColorPickerButton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>SDL0LED</tabstop>
|
||||
<tabstop>SDL1LED</tabstop>
|
||||
<tabstop>SDL2LED</tabstop>
|
||||
<tabstop>SDL3LED</tabstop>
|
||||
<tabstop>enableSDLPS5PlayerLED</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -33,13 +33,19 @@
|
||||
<widget class="QListWidget" name="bindList"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="bindListLabel">
|
||||
<property name="text">
|
||||
<string>Select the buttons which you want to trigger with this macro. All buttons are activated concurrently.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>bindList</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -52,13 +58,19 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="pressureLabel">
|
||||
<property name="text">
|
||||
<string>For buttons which are pressure sensitive, this slider controls how much force will be simulated when the macro is active.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pressure</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -116,6 +128,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -137,10 +152,13 @@
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="deadzoneLayout" stretch="0,1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="deadzoneLabel">
|
||||
<property name="text">
|
||||
<string>Deadzone:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>deadzone</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -190,6 +208,9 @@
|
||||
<property name="text">
|
||||
<string>Macro will toggle every N frames.</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -38,10 +38,10 @@
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">Controller Mapping Settings</span><br/>These settings fine-tune the behavior when mapping physical controllers to the emulated controllers.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
<enum>Qt::TextFormat::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -71,6 +71,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ignoreInversion</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -79,7 +82,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -92,12 +95,15 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<set>QDialogButtonBox::StandardButton::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>ignoreInversion</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<item row="5" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<set>QDialogButtonBox::StandardButton::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -40,6 +40,9 @@
|
||||
<property name="text">
|
||||
<string>Y Speed</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pointerYSpeedSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -63,7 +66,7 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -107,6 +110,9 @@
|
||||
<property name="text">
|
||||
<string>X Speed</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pointerXSpeedSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -130,7 +136,7 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -182,10 +188,10 @@
|
||||
<string><html><head/><body><p><span style=" font-weight:700;">Mouse Mapping Settings</span><br/>These settings fine-tune the behavior when mapping a mouse to the emulated controller.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
<enum>Qt::TextFormat::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -197,7 +203,7 @@
|
||||
<item row="4" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -226,6 +232,9 @@
|
||||
<property name="text">
|
||||
<string>Inertia</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pointerInertiaSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -249,7 +258,7 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -293,6 +302,9 @@
|
||||
<property name="text">
|
||||
<string>X Dead Zone</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pointerXDeadZoneSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -316,7 +328,7 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -360,6 +372,9 @@
|
||||
<property name="text">
|
||||
<string>Y Dead Zone</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>pointerYDeadZoneSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -383,7 +398,7 @@
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -410,6 +425,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>pointerXSpeedSlider</tabstop>
|
||||
<tabstop>pointerXDeadZoneSlider</tabstop>
|
||||
<tabstop>pointerYSpeedSlider</tabstop>
|
||||
<tabstop>pointerYDeadZoneSlider</tabstop>
|
||||
<tabstop>pointerInertiaSlider</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<property name="text">
|
||||
<string>Select Hosts</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hostList</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -36,7 +39,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -64,6 +67,11 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>hostList</tabstop>
|
||||
<tabstop>btnOK</tabstop>
|
||||
<tabstop>btnCancel</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
<property name="text">
|
||||
<string>Ethernet Device:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethDev</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
@@ -44,6 +47,9 @@
|
||||
<property name="text">
|
||||
<string>Ethernet Device Type:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethDevType</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
@@ -84,6 +90,9 @@
|
||||
<property name="text">
|
||||
<string>Subnet Mask:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethNetMask</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
@@ -91,6 +100,9 @@
|
||||
<property name="text">
|
||||
<string>Gateway Address:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethGatewayAddr</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
@@ -105,6 +117,9 @@
|
||||
<property name="text">
|
||||
<string>Intercept DHCP:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethInterceptDHCP</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -126,6 +141,9 @@
|
||||
<property name="text">
|
||||
<string>PS2 Address:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethPS2Addr</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
@@ -140,6 +158,9 @@
|
||||
<property name="text">
|
||||
<string>DNS1 Address:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethDNS1Addr</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
@@ -154,6 +175,9 @@
|
||||
<property name="text">
|
||||
<string>DNS2 Address:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethDNS2Addr</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
@@ -213,7 +237,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -230,12 +254,15 @@
|
||||
<property name="text">
|
||||
<string>Internal DNS can be selected using the DNS1/2 dropdowns, or by setting them to 192.0.2.1</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>ethHosts</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableView" name="ethHosts">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
<enum>QAbstractItemView::SelectionMode::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -326,10 +353,10 @@
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
<enum>QSlider::TickPosition::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>5</number>
|
||||
@@ -360,6 +387,9 @@
|
||||
<property name="text">
|
||||
<string>HDD File:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hddFile</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@@ -367,6 +397,9 @@
|
||||
<property name="text">
|
||||
<string>HDD Size (GiB):</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hddSizeSlider</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
@@ -382,7 +415,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -394,6 +427,35 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>ethEnabled</tabstop>
|
||||
<tabstop>ethDevType</tabstop>
|
||||
<tabstop>ethDev</tabstop>
|
||||
<tabstop>ethTabWidget</tabstop>
|
||||
<tabstop>ethInterceptDHCP</tabstop>
|
||||
<tabstop>ethPS2Addr</tabstop>
|
||||
<tabstop>ethNetMask</tabstop>
|
||||
<tabstop>ethNetMaskAuto</tabstop>
|
||||
<tabstop>ethGatewayAddr</tabstop>
|
||||
<tabstop>ethGatewayAuto</tabstop>
|
||||
<tabstop>ethDNS1Addr</tabstop>
|
||||
<tabstop>ethDNS1Mode</tabstop>
|
||||
<tabstop>ethDNS2Addr</tabstop>
|
||||
<tabstop>ethDNS2Mode</tabstop>
|
||||
<tabstop>ethHostAdd</tabstop>
|
||||
<tabstop>ethHostDel</tabstop>
|
||||
<tabstop>ethHostExport</tabstop>
|
||||
<tabstop>ethHostImport</tabstop>
|
||||
<tabstop>ethHostPerGame</tabstop>
|
||||
<tabstop>ethHosts</tabstop>
|
||||
<tabstop>hddEnabled</tabstop>
|
||||
<tabstop>hddLBA48</tabstop>
|
||||
<tabstop>hddFile</tabstop>
|
||||
<tabstop>hddBrowseFile</tabstop>
|
||||
<tabstop>hddSizeSlider</tabstop>
|
||||
<tabstop>hddSizeSpinBox</tabstop>
|
||||
<tabstop>hddCreate</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextBrowserInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -49,6 +52,9 @@
|
||||
<property name="text">
|
||||
<string>Automatically Analyze Program:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>analysisCondition</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -94,6 +100,10 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>analysisCondition</tabstop>
|
||||
<tabstop>generateSymbolsForIRXExportTables</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<string><html><head/><body><p><br/></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -168,6 +168,9 @@
|
||||
<property name="text">
|
||||
<string>Import from file (.elf, .sym, etc):</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>symbolFileTable</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -188,10 +191,10 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideLeft</enum>
|
||||
<enum>Qt::TextElideMode::ElideLeft</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
@@ -231,7 +234,7 @@
|
||||
<item>
|
||||
<spacer name="importSymbolFileSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -280,6 +283,9 @@
|
||||
<property name="text">
|
||||
<string>Scan Mode:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>functionScanMode</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -328,10 +334,10 @@
|
||||
<item>
|
||||
<spacer name="startSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
<enum>QSizePolicy::Policy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -346,6 +352,9 @@
|
||||
<property name="text">
|
||||
<string>Start:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>addressRangeStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -356,6 +365,9 @@
|
||||
<property name="text">
|
||||
<string>End:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>addressRangeEnd</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -364,10 +376,10 @@
|
||||
<item>
|
||||
<spacer name="endSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
<enum>QSizePolicy::Policy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -408,7 +420,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -420,6 +432,22 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>automaticallyClearSymbols</tabstop>
|
||||
<tabstop>symbolSourceScrollArea</tabstop>
|
||||
<tabstop>importFromElf</tabstop>
|
||||
<tabstop>importSymFileFromDefaultLocation</tabstop>
|
||||
<tabstop>demangleSymbols</tabstop>
|
||||
<tabstop>demangleParameters</tabstop>
|
||||
<tabstop>symbolFileTable</tabstop>
|
||||
<tabstop>addSymbolFile</tabstop>
|
||||
<tabstop>removeSymbolFile</tabstop>
|
||||
<tabstop>functionScanMode</tabstop>
|
||||
<tabstop>customAddressRange</tabstop>
|
||||
<tabstop>addressRangeStart</tabstop>
|
||||
<tabstop>addressRangeEnd</tabstop>
|
||||
<tabstop>grayOutOverwrittenFunctions</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -71,7 +71,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="saveDrawStats">
|
||||
<property name="text">
|
||||
<string>Save Draw Stats</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="saveFrameStats">
|
||||
<property name="text">
|
||||
<string>Save Frame Stats</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="saveTransferImages">
|
||||
<property name="text">
|
||||
<string>Save Transfer Image Data</string>
|
||||
@@ -85,6 +99,9 @@
|
||||
<property name="text">
|
||||
<string>Save Draw Start:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>saveDrawStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@@ -99,6 +116,9 @@
|
||||
<property name="text">
|
||||
<string>Save Draw Count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>saveDrawCount</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@@ -116,6 +136,9 @@
|
||||
<property name="text">
|
||||
<string>Save Frame Start:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>saveFrameStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
@@ -130,6 +153,9 @@
|
||||
<property name="text">
|
||||
<string>Save Frame Count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>saveFrameCount</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
@@ -147,6 +173,9 @@
|
||||
<property name="text">
|
||||
<string>Hardware Dump Directory:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>hwDumpDirectory</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
@@ -154,6 +183,9 @@
|
||||
<property name="text">
|
||||
<string>Software Dump Directory:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>swDumpDirectory</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
@@ -204,7 +236,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -216,6 +248,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>dumpGSData</tabstop>
|
||||
<tabstop>saveFrame</tabstop>
|
||||
<tabstop>saveRT</tabstop>
|
||||
<tabstop>saveDepth</tabstop>
|
||||
<tabstop>saveTexture</tabstop>
|
||||
<tabstop>saveAlpha</tabstop>
|
||||
<tabstop>saveInfo</tabstop>
|
||||
<tabstop>saveTransferImages</tabstop>
|
||||
<tabstop>saveDrawStart</tabstop>
|
||||
<tabstop>saveDrawCount</tabstop>
|
||||
<tabstop>saveFrameStart</tabstop>
|
||||
<tabstop>saveFrameCount</tabstop>
|
||||
<tabstop>hwDumpDirectory</tabstop>
|
||||
<tabstop>hwDumpBrowse</tabstop>
|
||||
<tabstop>hwDumpOpen</tabstop>
|
||||
<tabstop>swDumpDirectory</tabstop>
|
||||
<tabstop>swDumpBrowse</tabstop>
|
||||
<tabstop>swDumpOpen</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
<item>
|
||||
<spacer name="eeLoggingSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -286,7 +286,7 @@
|
||||
<item>
|
||||
<spacer name="iopLoggingSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -304,7 +304,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -316,6 +316,41 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>chkEnable</tabstop>
|
||||
<tabstop>chkEECOP0</tabstop>
|
||||
<tabstop>chkEECOP1</tabstop>
|
||||
<tabstop>chkEECOP2</tabstop>
|
||||
<tabstop>chkEER5900</tabstop>
|
||||
<tabstop>chkEECache</tabstop>
|
||||
<tabstop>chkEEMemory</tabstop>
|
||||
<tabstop>chkEEMMIO</tabstop>
|
||||
<tabstop>chkEEUNKNWNMMIO</tabstop>
|
||||
<tabstop>chkEEDMARegs</tabstop>
|
||||
<tabstop>chkEEDMACTRL</tabstop>
|
||||
<tabstop>chkEEMSKPATH3</tabstop>
|
||||
<tabstop>chkEEMFIFO</tabstop>
|
||||
<tabstop>chkEEIPU</tabstop>
|
||||
<tabstop>chkEECounters</tabstop>
|
||||
<tabstop>chkEEVIFCodes</tabstop>
|
||||
<tabstop>chkEEGIFTags</tabstop>
|
||||
<tabstop>chkEEVIF</tabstop>
|
||||
<tabstop>chkEEGIF</tabstop>
|
||||
<tabstop>chkEEBIOS</tabstop>
|
||||
<tabstop>chkEESIF</tabstop>
|
||||
<tabstop>chkIOPCOP2</tabstop>
|
||||
<tabstop>chkIOPR3000A</tabstop>
|
||||
<tabstop>chkIOPMemcards</tabstop>
|
||||
<tabstop>chkIOPPad</tabstop>
|
||||
<tabstop>chkIOPDMARegs</tabstop>
|
||||
<tabstop>chkIOPDMACTRL</tabstop>
|
||||
<tabstop>chkIOPMMIO</tabstop>
|
||||
<tabstop>chkIOPUNKNWNMMIO</tabstop>
|
||||
<tabstop>chkIOPCounters</tabstop>
|
||||
<tabstop>chkIOPCDVD</tabstop>
|
||||
<tabstop>chkIOPMDEC</tabstop>
|
||||
<tabstop>chkIOPBIOS</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user