mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
248 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eccec21ada | ||
|
|
03aaf7db6a | ||
|
|
6d9e0482b4 | ||
|
|
34f2328a79 | ||
|
|
2569193b05 | ||
|
|
b935ec3d19 | ||
|
|
e0e6b0d9a5 | ||
|
|
580218d495 | ||
|
|
519f280fa5 | ||
|
|
a33ee13bb4 | ||
|
|
0c70cc7e5a | ||
|
|
2cba346ff5 | ||
|
|
db2509edb3 | ||
|
|
e3063d6cd6 | ||
|
|
8d30e8cee8 | ||
|
|
ff2f1998ad | ||
|
|
7942ee438a | ||
|
|
f322dfb1d4 | ||
|
|
a7f5ddfe0d | ||
|
|
0cdfb75fd0 | ||
|
|
35624a12d9 | ||
|
|
9b147cc57c | ||
|
|
10e13cfece | ||
|
|
7b2eb7bc47 | ||
|
|
ab1cb802d8 | ||
|
|
366cdd8df0 | ||
|
|
bc3cfb1373 | ||
|
|
db6792af2e | ||
|
|
a1485fb7cd | ||
|
|
c72c309218 | ||
|
|
58899a9ed3 | ||
|
|
0823c70460 | ||
|
|
e5c29a3975 | ||
|
|
1174ae99c9 | ||
|
|
e2d3680038 | ||
|
|
8630893cb1 | ||
|
|
53598b970d | ||
|
|
89de00ac36 | ||
|
|
d5ddf07958 | ||
|
|
30dcf4a14a | ||
|
|
a87710e4bc | ||
|
|
a12f87fec2 | ||
|
|
8ba9bba094 | ||
|
|
1363571c14 | ||
|
|
80de666fcc | ||
|
|
ff0a2f84fa | ||
|
|
0676f145bc | ||
|
|
e19ae2bf60 | ||
|
|
7782d930d5 | ||
|
|
d1a53fe29b | ||
|
|
c484cf286c | ||
|
|
f8882c4da6 | ||
|
|
52c17e67a5 | ||
|
|
615cd00147 | ||
|
|
cb0bf953d3 | ||
|
|
26a68ef76a | ||
|
|
e4c1dc2359 | ||
|
|
40425e3bee | ||
|
|
e51e4a35fe | ||
|
|
bd1b9ea718 | ||
|
|
faaa376232 | ||
|
|
e9ca1a6ead | ||
|
|
4d3149eacb | ||
|
|
78822c96fb | ||
|
|
a78617b987 | ||
|
|
3059ab2b12 | ||
|
|
1d0f6cc5b7 | ||
|
|
38a35043a8 | ||
|
|
7385cbe40a | ||
|
|
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 | ||
|
|
d9a2618b7a | ||
|
|
dca0291cfb | ||
|
|
b261873471 | ||
|
|
bfd01c913a | ||
|
|
818b3fe779 | ||
|
|
66a28e4488 | ||
|
|
28e2ecf920 | ||
|
|
d3dbf53fa7 | ||
|
|
8fb2940f25 | ||
|
|
55498762f9 | ||
|
|
50baaf39d6 | ||
|
|
4743ccac8c | ||
|
|
0dc3fc6228 | ||
|
|
a7a4583c84 | ||
|
|
6b52937262 | ||
|
|
df9caf6fb8 | ||
|
|
be5f8d2e60 | ||
|
|
b0e01ca518 | ||
|
|
4e85272393 | ||
|
|
bffed9a839 | ||
|
|
7ed0c0d031 | ||
|
|
ae6e4c98f6 | ||
|
|
38cfa9912d | ||
|
|
b02318e2b6 | ||
|
|
db45263221 | ||
|
|
3fd9625f1c | ||
|
|
2978b6050d | ||
|
|
274acddcf1 | ||
|
|
8dffc85707 | ||
|
|
f799631a70 | ||
|
|
d744f0dfeb | ||
|
|
bdb8de6d3b | ||
|
|
e751f367ca | ||
|
|
13f2d87ba8 | ||
|
|
3cac2cf7c2 | ||
|
|
a67409bfc6 | ||
|
|
6a556c9968 | ||
|
|
4d93285ca2 | ||
|
|
98c35a308d | ||
|
|
7da97e6d80 | ||
|
|
edf686752a | ||
|
|
b7e17646a3 | ||
|
|
3f437e7496 | ||
|
|
7ab6c62dee | ||
|
|
2a7bf35f20 | ||
|
|
08552a83cc | ||
|
|
ee417ee4c5 | ||
|
|
869837f5f0 | ||
|
|
7ab6bac39a | ||
|
|
e388294004 | ||
|
|
bba5ef67ff | ||
|
|
83dc2de6ca | ||
|
|
f47fbda0e6 |
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:
|
||||
|
||||
2
.github/workflows/lint_gamedb.yml
vendored
2
.github/workflows/lint_gamedb.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Install Packages
|
||||
run: |
|
||||
npm install -g ajv-cli prettier
|
||||
sudo apt-get -y install yamllint
|
||||
pip install yamllint
|
||||
|
||||
- name: Validate YAML
|
||||
run: |
|
||||
|
||||
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
|
||||
|
||||
15
.github/workflows/macos_build.yml
vendored
15
.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
|
||||
@@ -91,7 +94,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh', '.github/workflows/scripts/common/*.patch') }}
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/*', '.github/workflows/scripts/common/*.patch') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
@@ -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@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
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@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
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
|
||||
|
||||
|
||||
18
.github/workflows/scripts/linux/appimage-qt.sh
vendored
18
.github/workflows/scripts/linux/appimage-qt.sh
vendored
@@ -50,12 +50,6 @@ declare -a MANUAL_LIBS=(
|
||||
"libfreetype.so.6"
|
||||
)
|
||||
|
||||
declare -a REMOVE_LIBS=(
|
||||
'libwayland-client.so*'
|
||||
'libwayland-cursor.so*'
|
||||
'libwayland-egl.so*'
|
||||
)
|
||||
|
||||
set -e
|
||||
|
||||
LINUXDEPLOY=./linuxdeploy-x86_64.AppImage
|
||||
@@ -130,7 +124,7 @@ echo "Running linuxdeploy to create AppDir..."
|
||||
# Interestingly, specifying the module doesn't copy the module, only the required plugins for it
|
||||
# https://github.com/linuxdeploy/linuxdeploy-plugin-qt/issues/160#issuecomment-2655543893
|
||||
EXTRA_QT_MODULES="core;gui;svg;waylandclient;waylandcompositor;widgets;xcbqpa" \
|
||||
EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
|
||||
EXTRA_PLATFORM_PLUGINS="libqwayland.so" \
|
||||
DEPLOY_PLATFORM_THEMES="1" \
|
||||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
@@ -140,16 +134,6 @@ $LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt
|
||||
echo "Copying resources into AppDir..."
|
||||
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
|
||||
|
||||
# Why do we have to manually remove these libs? Because the linuxdeploy Qt plugin
|
||||
# copies them, not the "main" linuxdeploy binary, and plugins don't inherit the
|
||||
# include list...
|
||||
for lib in "${REMOVE_LIBS[@]}"; do
|
||||
for libpath in $(find "$OUTDIR/usr/lib" -name "$lib"); do
|
||||
echo " Removing problematic library ${libpath}."
|
||||
rm -f "$libpath"
|
||||
done
|
||||
done
|
||||
|
||||
# Restore unstripped deps (for cache).
|
||||
rm -fr "$DEPSDIR"
|
||||
mv "$DEPSDIR.bak" "$DEPSDIR"
|
||||
|
||||
@@ -20,12 +20,12 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.24
|
||||
QT=6.9.2
|
||||
SDL=SDL3-3.2.26
|
||||
QT=6.10.1
|
||||
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,22 +44,22 @@ 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
|
||||
44be9c9ecfe04129c4dea0a7e1b36ad476c9cc07c292016ac98e7b41514f2440 qtbase-everywhere-src-$QT.tar.xz
|
||||
8a023f7e2f57dedc02e2ab10c975f7cb3cccac9b8f0823c12fd6824834549139 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
d984cab8f26334aa1c15e5b8f0cd9f1b7c0c1289fe0b68c1c84ab469b75605a5 qtsvg-everywhere-src-$QT.tar.xz
|
||||
d8b7f7e8e970cc0b975205fd6d5832ea917ef3e751df69b97439c1cddd67a489 qttools-everywhere-src-$QT.tar.xz
|
||||
c73bb6281ed365c0f954f4b1b6e1b13e1b3fefd94854f46fcd9a412f641f7ed6 qttranslations-everywhere-src-$QT.tar.xz
|
||||
cad79806565568f12f9983fed69219416abcee9d5deef4abdfcf94aa2eef7781 qtwayland-everywhere-src-$QT.tar.xz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
|
||||
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
|
||||
49bf6db800227a6b2c971f4c5d03dd1e81297e7ffb296ce4a96437304f27cb13 qtwayland-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
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 ..
|
||||
|
||||
196
.github/workflows/scripts/linux/build-dependencies-runner.sh
vendored
Executable file
196
.github/workflows/scripts/linux/build-dependencies-runner.sh
vendored
Executable file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Syntax: $0 <output directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPTDIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
INSTALLDIR="$1"
|
||||
if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.0.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.22
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.3
|
||||
SHADERC_GLSLANG=efd24d75bcbc55620e759f6bf42c45a32abac5f8
|
||||
SHADERC_SPIRVHEADERS=2a611a970fdbc41ac2e3e328802aed9985352dca
|
||||
SHADERC_SPIRVTOOLS=33e02568181e3312f49a3cf33df470bf96ef293a
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
c4a398539c3e0fdc9a82dfe7824d0438cae78c1e2124e7c6ada3dfa600cdb6c8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
bea672eb96ee36c2cbeb911b9bac66dfe989b3ad9a9943101e00aeb2df2aefdb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-o "freetype-$FREETYPE.tar.xz" "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz/download" \
|
||||
-o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
-O "https://download.sourceforge.net/libpng-apng/libpng-$LIBPNG-apng.patch.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://github.com/lz4/lz4/releases/download/v$LZ4/lz4-$LZ4.tar.gz" \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
-o "shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Tools/archive/$SHADERC_SPIRVTOOLS.tar.gz" \
|
||||
-o "plutovg-$PLUTOVG.tar.gz" "https://github.com/sammycage/plutovg/archive/v$PLUTOVG.tar.gz" \
|
||||
-o "plutosvg-$PLUTOSVG.tar.gz" "https://github.com/sammycage/plutosvg/archive/v$PLUTOSVG.tar.gz"
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
unzip "$LIBBACKTRACE.zip"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$INSTALLDIR"
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Building libpng..."
|
||||
rm -fr "libpng-$LIBPNG"
|
||||
tar xf "libpng-$LIBPNG.tar.xz"
|
||||
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
|
||||
cd "libpng-$LIBPNG"
|
||||
patch -p1 < "../libpng-$LIBPNG-apng.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building LZ4..."
|
||||
rm -fr "lz4-$LZ4"
|
||||
tar xf "lz4-$LZ4.tar.gz"
|
||||
cd "lz4-$LZ4"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DLZ4_BUILD_CLI=OFF -DLZ4_BUILD_LEGACY_LZ4C=OFF -B build-dir -G Ninja build/cmake
|
||||
cmake --build build-dir --parallel
|
||||
ninja -C build-dir install
|
||||
cd ..
|
||||
|
||||
echo "Building Zstandard..."
|
||||
rm -fr "zstd-$ZSTD"
|
||||
tar xf "zstd-$ZSTD.tar.gz"
|
||||
cd "zstd-$ZSTD"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType without HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building HarfBuzz..."
|
||||
rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building WebP..."
|
||||
rm -fr "libwebp-$LIBWEBP"
|
||||
tar xf "libwebp-$LIBWEBP.tar.gz"
|
||||
cd "libwebp-$LIBWEBP"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -B build -G Ninja \
|
||||
-DWEBP_BUILD_ANIM_UTILS=OFF -DWEBP_BUILD_CWEBP=OFF -DWEBP_BUILD_DWEBP=OFF -DWEBP_BUILD_GIF2WEBP=OFF -DWEBP_BUILD_IMG2WEBP=OFF \
|
||||
-DWEBP_BUILD_VWEBP=OFF -DWEBP_BUILD_WEBPINFO=OFF -DWEBP_BUILD_WEBPMUX=OFF -DWEBP_BUILD_EXTRAS=OFF -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType with HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building SDL..."
|
||||
rm -fr "$SDL"
|
||||
tar xf "$SDL.tar.gz"
|
||||
cd "$SDL"
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building PlutoVG..."
|
||||
rm -fr "plutovg-$PLUTOVG"
|
||||
tar xf "plutovg-$PLUTOVG.tar.gz"
|
||||
cd "plutovg-$PLUTOVG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building shaderc..."
|
||||
rm -fr "shaderc-$SHADERC"
|
||||
tar xf "shaderc-$SHADERC.tar.gz"
|
||||
cd "shaderc-$SHADERC"
|
||||
cd third_party
|
||||
tar xf "../../shaderc-glslang-$SHADERC_GLSLANG.tar.gz"
|
||||
mv "glslang-$SHADERC_GLSLANG" "glslang"
|
||||
tar xf "../../shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz"
|
||||
mv "SPIRV-Headers-$SHADERC_SPIRVHEADERS" "spirv-headers"
|
||||
tar xf "../../shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz"
|
||||
mv "SPIRV-Tools-$SHADERC_SPIRVTOOLS" "spirv-tools"
|
||||
cd ..
|
||||
patch -p1 < "$SCRIPTDIR/../common/shaderc-changes.patch"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DSHADERC_SKIP_TESTS=ON -DSHADERC_SKIP_EXAMPLES=ON -DSHADERC_SKIP_COPYRIGHT_CHECK=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -r deps-build
|
||||
@@ -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
.github/workflows/scripts/macos/build-dependencies-universal.sh
vendored
Normal file → Executable file
40
.github/workflows/scripts/macos/build-dependencies-universal.sh
vendored
Normal file → Executable file
@@ -40,17 +40,17 @@ 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
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
@@ -80,26 +80,26 @@ 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
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
9fd58144081654c3373768dd96ead294023830927b14fe3d3c1ef641fb324753 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
|
||||
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
|
||||
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
|
||||
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
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
|
||||
@@ -285,6 +285,10 @@ echo "Installing Qt Base..."
|
||||
rm -fr "qtbase-everywhere-src-$QT"
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
|
||||
# Patch Qt to support macOS 11
|
||||
patch -p1 < "$SCRIPTDIR/qt-macos11compat.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.
|
||||
@@ -320,7 +324,7 @@ tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -331,7 +335,7 @@ tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_system_webp=ON
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF -DFEATURE_system_webp=ON
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -342,7 +346,7 @@ tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -371,7 +375,7 @@ tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -391,8 +395,8 @@ rm -fr "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
tar xf "KDDockWidgets-$KDDOCKWIDGETS.tar.gz"
|
||||
cd "KDDockWidgets-$KDDOCKWIDGETS"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build
|
||||
cmake --build build --parallel
|
||||
cmake --install build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building PlutoVG..."
|
||||
|
||||
@@ -22,17 +22,17 @@ 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
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
KDDOCKWIDGETS=2.3.0
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.1
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
@@ -54,32 +54,33 @@ CMAKE_COMMON=(
|
||||
-DCMAKE_PREFIX_PATH="$INSTALLDIR"
|
||||
-DCMAKE_INSTALL_PREFIX="$INSTALLDIR"
|
||||
-DCMAKE_OSX_ARCHITECTURES="x86_64"
|
||||
-DCMAKE_APPLE_SILICON_PROCESSOR="x86_64"
|
||||
-DCMAKE_INSTALL_NAME_DIR='$<INSTALL_PREFIX>/lib'
|
||||
)
|
||||
|
||||
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
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
687ddc0c7cb128a3ea58e159b5129252537c27ede0c32a93f11f03127f0c0165 libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097 qtbase-everywhere-src-$QT.tar.xz
|
||||
9fd58144081654c3373768dd96ead294023830927b14fe3d3c1ef641fb324753 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b qtsvg-everywhere-src-$QT.tar.xz
|
||||
f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f qttools-everywhere-src-$QT.tar.xz
|
||||
dcc762acac043b9bb5e4d369b6d6f53e0ecfcf76a408fe0db5f7ef071c9d6dc8 qttranslations-everywhere-src-$QT.tar.xz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
498eabdf2381db96f808942b3e3c765f6360fe6c0e9961f0a45ff7a4c68d7a72 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
c02f355a58f3bbcf404a628bf488b6aeb2d84a94c269afdb86f6e529343ab01f qtsvg-everywhere-src-$QT.tar.xz
|
||||
8148408380ffea03101a26305c812b612ea30dbc07121e58707601522404d49b qttools-everywhere-src-$QT.tar.xz
|
||||
8e49a2df88a12c376a479ae7bd272a91cf57ebb4e7c0cf7341b3565df99d2314 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
|
||||
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
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
|
||||
@@ -233,26 +234,15 @@ rm -fr "qtbase-everywhere-src-$QT"
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
|
||||
# Patch Qt to support macOS 11
|
||||
patch -p1 < "$SCRIPTDIR/qt-macos11compat.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.
|
||||
|
||||
# https://github.com/qt/qtbase/commit/7b018629c3c3ab23665bf1da00c43c1546042035
|
||||
# The QProcess default wait time of 30s may be too short in e.g. CI environments where processes may be blocked
|
||||
# for a longer time waiting for CPU or IO.
|
||||
|
||||
patch -u src/tools/macdeployqt/shared/shared.cpp <<EOF
|
||||
--- shared.cpp
|
||||
+++ shared.cpp
|
||||
@@ -152,7 +152,7 @@
|
||||
LogDebug() << " inspecting" << binaryPath;
|
||||
QProcess otool;
|
||||
otool.start("otool", QStringList() << "-L" << binaryPath);
|
||||
- otool.waitForFinished();
|
||||
+ otool.waitForFinished(-1);
|
||||
|
||||
if (otool.exitStatus() != QProcess::NormalExit || otool.exitCode() != 0) {
|
||||
LogError() << otool.readAllStandardError();
|
||||
@@ -1122,14 +1122,8 @@
|
||||
addPlugins(QStringLiteral("networkinformation"));
|
||||
}
|
||||
@@ -271,7 +261,7 @@ patch -u src/tools/macdeployqt/shared/shared.cpp <<EOF
|
||||
|
||||
// Platforminputcontext plugins if QtGui is in use
|
||||
EOF
|
||||
cmake -B build "${CMAKE_COMMON[@]}" -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake -B build "${CMAKE_COMMON[@]}" -DCMAKE_BUILD_TYPE=MinSizeRel -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
@@ -282,7 +272,7 @@ tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -293,7 +283,7 @@ tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DFEATURE_system_webp=ON
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF -DFEATURE_system_webp=ON
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -304,7 +294,7 @@ tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -333,7 +323,7 @@ tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" -DQT_GENERATE_SBOM=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
116
.github/workflows/scripts/macos/qt-macos11compat.patch
vendored
Normal file
116
.github/workflows/scripts/macos/qt-macos11compat.patch
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
diff --git a/.cmake.conf b/.cmake.conf
|
||||
--- a/.cmake.conf
|
||||
+++ b/.cmake.conf
|
||||
@@ -51,7 +51,7 @@ set(QT_MAX_NEW_POLICY_CMAKE_VERSION_QT_APPLE "3.21")
|
||||
set(QT_SUPPORTED_MIN_MACOS_SDK_VERSION "14")
|
||||
set(QT_SUPPORTED_MAX_MACOS_SDK_VERSION "26")
|
||||
set(QT_SUPPORTED_MIN_MACOS_XCODE_VERSION "15")
|
||||
-set(QT_SUPPORTED_MIN_MACOS_VERSION "13")
|
||||
+set(QT_SUPPORTED_MIN_MACOS_VERSION "11")
|
||||
set(QT_SUPPORTED_MAX_MACOS_VERSION_TESTED "26")
|
||||
|
||||
set(QT_SUPPORTED_MIN_IOS_SDK_VERSION "17")
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -12,6 +12,10 @@ cmake_minimum_required(VERSION 3.16)
|
||||
# Get the repo version and CMake policy details
|
||||
include(.cmake.conf)
|
||||
|
||||
+if(APPLE)
|
||||
+ add_compile_options(-Werror=unguarded-availability-new)
|
||||
+endif()
|
||||
+
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtBaseHelpers.cmake)
|
||||
|
||||
qt_internal_check_if_path_has_symlinks("${CMAKE_BINARY_DIR}")
|
||||
diff --git a/src/corelib/global/qsysinfo.cpp b/src/corelib/global/qsysinfo.cpp
|
||||
--- a/src/corelib/global/qsysinfo.cpp
|
||||
+++ b/src/corelib/global/qsysinfo.cpp
|
||||
@@ -1027,7 +1027,7 @@ QByteArray QSysInfo::machineUniqueId()
|
||||
{
|
||||
#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
|
||||
char uuid[UuidStringLen + 1];
|
||||
- io_service_t service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
|
||||
+ io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
|
||||
QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
|
||||
CFStringGetCString(stringRef, uuid, sizeof(uuid), kCFStringEncodingMacRoman);
|
||||
return QByteArray(uuid);
|
||||
diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm
|
||||
--- a/src/corelib/kernel/qcore_mac.mm
|
||||
+++ b/src/corelib/kernel/qcore_mac.mm
|
||||
@@ -367,7 +367,7 @@ bool qt_apple_runningWithLiquidGlass()
|
||||
return config;
|
||||
#endif
|
||||
|
||||
- QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMainPortDefault, "IODeviceTree:/options");
|
||||
+ QIOType<io_registry_entry_t> nvram = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
|
||||
if (!nvram) {
|
||||
qWarning("Failed to locate NVRAM entry in IO registry");
|
||||
return {};
|
||||
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
|
||||
--- a/src/gui/platform/darwin/qappleiconengine.mm
|
||||
+++ b/src/gui/platform/darwin/qappleiconengine.mm
|
||||
@@ -366,12 +366,16 @@
|
||||
weight:NSFontWeightRegular
|
||||
scale:NSImageSymbolScaleLarge];
|
||||
|
||||
+ auto *primaryColor = [NSColor colorWithSRGBRed:color.redF()
|
||||
+ green:color.greenF()
|
||||
+ blue:color.blueF()
|
||||
+ alpha:color.alphaF()];
|
||||
+
|
||||
+ if (@available(macOS 13, *)) {
|
||||
+
|
||||
// Apply tint color first, which switches the configuration to palette mode
|
||||
config = [config configurationByApplyingConfiguration:
|
||||
- [NSImageSymbolConfiguration configurationWithPaletteColors:@[
|
||||
- [NSColor colorWithSRGBRed:color.redF() green:color.greenF()
|
||||
- blue:color.blueF() alpha:color.alphaF()]
|
||||
- ]]];
|
||||
+ [NSImageSymbolConfiguration configurationWithPaletteColors:@[primaryColor]]];
|
||||
|
||||
// Then switch back to monochrome, as palette mode gives a different look
|
||||
// than monochrome, even with a single color.
|
||||
@@ -379,6 +383,18 @@
|
||||
[NSImageSymbolConfiguration configurationPreferringMonochrome]];
|
||||
|
||||
return [image imageWithSymbolConfiguration:config];
|
||||
+
|
||||
+ } else {
|
||||
+ NSImage *configuredImage = [image imageWithSymbolConfiguration:config];
|
||||
+ return [NSImage imageWithSize:configuredImage.size flipped:NO
|
||||
+ drawingHandler:^BOOL(NSRect) {
|
||||
+ [primaryColor set];
|
||||
+ NSRect imageRect = {NSZeroPoint, configuredImage.size};
|
||||
+ [configuredImage drawInRect:imageRect];
|
||||
+ NSRectFillUsingOperation(imageRect, NSCompositingOperationSourceIn);
|
||||
+ return YES;
|
||||
+ }];
|
||||
+ }
|
||||
}
|
||||
#elif defined(QT_PLATFORM_UIKIT)
|
||||
auto *configuredImage(const UIImage *image, const QColor &color)
|
||||
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
|
||||
@@ -323,6 +323,8 @@ a normal (not maximized or full screen) top-level window.
|
||||
m_view.safeAreaInsets.bottom
|
||||
};
|
||||
|
||||
+ if (@available(macOS 12, *)) {
|
||||
+
|
||||
// The screen's safe area insets represent the distances from the screen's
|
||||
// edges at which content isn't obscured. The view's safe area margins do
|
||||
// not include the screen's insets automatically, so we need to manually
|
||||
@@ -355,6 +357,10 @@ a normal (not maximized or full screen) top-level window.
|
||||
};
|
||||
|
||||
return (screenSafeAreaMargins | viewSafeAreaMargins).toMargins();
|
||||
+
|
||||
+ } else {
|
||||
+ return viewSafeAreaMargins.toMargins();
|
||||
+ }
|
||||
}
|
||||
|
||||
void QCocoaWindow::updateSafeAreaMarginsIfNeeded()
|
||||
@@ -46,17 +46,17 @@ 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 QT=6.9.2
|
||||
set LIBPNGLONG=1.6.50
|
||||
set QTMINOR=6.9
|
||||
set SDL=SDL3-3.2.26
|
||||
set QT=6.10.1
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
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,17 +71,17 @@ 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 "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 97d59c78e40b4ddd018738d285a12afc320b57f8265a3f760353739a3619ccdb || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f2fc6ff382c6f3af79493d0709dbd64847d0356313518f094f9096315f2fdb30 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" af80bb671ea0f66c0036ce7041a56b0e550fc94fb88d2c77b5b6a3e33e42139b || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" d2f4c7a4a12630e879702353f944f96a5d8e764771b5a5f04163334ad61b39db || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 3e168d1b081ee3a2175fe1bd97ad03bb40fe7ce38a37e99923a19f0e7ec4d81c || 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" c43f471a808b07fc541528410e94ce89c6745bdc1d744492e19911d35fbf7d33 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 2d828d8c999fdd18167937c071781c22321c643b04a106c714411c2356cdb26d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" ddd74a417d2397eb085d047a9b6ba52b76e748055817f728fe691f8456035d23 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" db8e49ed50912c3c064a4f9ada7791c09eccec5a8d53463a19608eaab17679f0 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 868eb651e395d48ade5932ef2c386e606e054eb5888ebe5284fbd8cb63ed935a || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
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
|
||||
|
||||
@@ -96,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...
|
||||
@@ -197,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,17 +44,17 @@ 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.9.2
|
||||
set QTMINOR=6.9
|
||||
set QT=6.10.1
|
||||
set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
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,17 +69,17 @@ 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 "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 97d59c78e40b4ddd018738d285a12afc320b57f8265a3f760353739a3619ccdb || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f2fc6ff382c6f3af79493d0709dbd64847d0356313518f094f9096315f2fdb30 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" af80bb671ea0f66c0036ce7041a56b0e550fc94fb88d2c77b5b6a3e33e42139b || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" d2f4c7a4a12630e879702353f944f96a5d8e764771b5a5f04163334ad61b39db || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 3e168d1b081ee3a2175fe1bd97ad03bb40fe7ce38a37e99923a19f0e7ec4d81c || 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" c43f471a808b07fc541528410e94ce89c6745bdc1d744492e19911d35fbf7d33 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 2d828d8c999fdd18167937c071781c22321c643b04a106c714411c2356cdb26d || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" ddd74a417d2397eb085d047a9b6ba52b76e748055817f728fe691f8456035d23 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" db8e49ed50912c3c064a4f9ada7791c09eccec5a8d53463a19608eaab17679f0 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 868eb651e395d48ade5932ef2c386e606e054eb5888ebe5284fbd8cb63ed935a || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
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
|
||||
|
||||
@@ -94,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%"
|
||||
@@ -194,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...
|
||||
@@ -233,7 +233,7 @@ ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
echo Building Qt Tools...
|
||||
rmdir /S /Q "qtimageformats-everywhere-src-%QT%"
|
||||
rmdir /S /Q "qttools-everywhere-src-%QT%"
|
||||
%SEVENZIP% x "qttools-everywhere-src-%QT%.zip" || goto error
|
||||
cd "qttools-everywhere-src-%QT%" || goto error
|
||||
mkdir build || goto error
|
||||
|
||||
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: |
|
||||
|
||||
2
.github/workflows/windows_deps_dispatch.yml
vendored
2
.github/workflows/windows_deps_dispatch.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dispatch to windows-dependencies repo
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ secrets.DEPS_REPO_DISPATCH_ACCESS_TOKEN }}
|
||||
repository: pcsx2/pcsx2-windows-dependencies
|
||||
|
||||
24
3rdparty/ccc/src/ccc/symbol_database.cpp
vendored
24
3rdparty/ccc/src/ccc/symbol_database.cpp
vendored
@@ -113,13 +113,27 @@ typename SymbolList<SymbolType>::AddressToHandleMapIterators SymbolList<SymbolTy
|
||||
template <typename SymbolType>
|
||||
typename SymbolList<SymbolType>::AddressToHandleMapIterators SymbolList<SymbolType>::handles_from_address_range(AddressRange range) const
|
||||
{
|
||||
if(range.low.valid()) {
|
||||
return {m_address_to_handle.lower_bound(range.low.value), m_address_to_handle.lower_bound(range.high.value)};
|
||||
} else if(range.high.valid()) {
|
||||
return {m_address_to_handle.begin(), m_address_to_handle.lower_bound(range.high.value)};
|
||||
typename AddressToHandleMap::const_iterator begin, end;
|
||||
if (range.low.valid() && range.high.valid()) {
|
||||
if (range.low.value < range.high.value) {
|
||||
begin = m_address_to_handle.lower_bound(range.low.value);
|
||||
end = m_address_to_handle.lower_bound(range.high.value);
|
||||
} else {
|
||||
begin = m_address_to_handle.end();
|
||||
end = m_address_to_handle.end();
|
||||
}
|
||||
} else if (range.low.valid()) {
|
||||
begin = m_address_to_handle.lower_bound(range.low.value);
|
||||
end = m_address_to_handle.end();
|
||||
} else if (range.high.valid()) {
|
||||
begin = m_address_to_handle.begin();
|
||||
end = m_address_to_handle.lower_bound(range.high.value);
|
||||
} else {
|
||||
return {m_address_to_handle.end(), m_address_to_handle.end()};
|
||||
begin = m_address_to_handle.end();
|
||||
end = m_address_to_handle.end();
|
||||
}
|
||||
|
||||
return {begin, end};
|
||||
}
|
||||
|
||||
template <typename SymbolType>
|
||||
|
||||
187
3rdparty/fmt/ChangeLog.md
vendored
187
3rdparty/fmt/ChangeLog.md
vendored
@@ -1,3 +1,176 @@
|
||||
# 12.0.0 - 2025-09-17
|
||||
|
||||
- Optimized the default floating point formatting
|
||||
(https://github.com/fmtlib/fmt/issues/3675,
|
||||
https://github.com/fmtlib/fmt/issues/4516). In particular, formatting a
|
||||
`double` with format string compilation into a stack allocated buffer is
|
||||
more than 60% faster in version 12.0 compared to 11.2 according to
|
||||
[dtoa-benchmark](https://github.com/fmtlib/dtoa-benchmark):
|
||||
|
||||
```
|
||||
Function Time (ns) Speedup
|
||||
fmt11 34.471 1.00x
|
||||
fmt12 21.000 1.64x
|
||||
```
|
||||
|
||||
<img width="766" height="609" src="https://github.com/user-attachments/assets/d7d768ad-7543-468c-b0bb-449abf73b31b" />
|
||||
|
||||
- Added `constexpr` support to `fmt::format`. For example:
|
||||
|
||||
```c++
|
||||
#include <fmt/compile.h>
|
||||
|
||||
using namespace fmt::literals;
|
||||
std::string s = fmt::format(""_cf, 42);
|
||||
```
|
||||
|
||||
now works at compile time provided that `std::string` supports `constexpr`
|
||||
(https://github.com/fmtlib/fmt/issues/3403,
|
||||
https://github.com/fmtlib/fmt/pull/4456). Thanks @msvetkin.
|
||||
|
||||
- Added `FMT_STATIC_FORMAT` that allows formatting into a string of the exact
|
||||
required size at compile time.
|
||||
|
||||
For example:
|
||||
|
||||
```c++
|
||||
#include <fmt/compile.h>
|
||||
|
||||
constexpr auto s = FMT_STATIC_FORMAT("{}", 42);
|
||||
```
|
||||
|
||||
compiles to just
|
||||
|
||||
```s
|
||||
__ZL1s:
|
||||
.asciiz "42"
|
||||
```
|
||||
|
||||
It can be accessed as a C string with `s.c_str()` or as a string view with
|
||||
`s.str()`.
|
||||
|
||||
- Improved C++20 module support
|
||||
(https://github.com/fmtlib/fmt/pull/4451,
|
||||
https://github.com/fmtlib/fmt/pull/4459,
|
||||
https://github.com/fmtlib/fmt/pull/4476,
|
||||
https://github.com/fmtlib/fmt/pull/4488,
|
||||
https://github.com/fmtlib/fmt/issues/4491,
|
||||
https://github.com/fmtlib/fmt/pull/4495).
|
||||
Thanks @arBmind, @tkhyn, @Mishura4, @anonymouspc and @autoantwort.
|
||||
|
||||
- Switched to using estimated display width in precision. For example:
|
||||
|
||||
```c++
|
||||
fmt::print("|{:.4}|\n|1234|\n", "🐱🐱🐱");
|
||||
```
|
||||
|
||||
prints
|
||||
|
||||

|
||||
|
||||
because `🐱` has an estimated width of 2
|
||||
(https://github.com/fmtlib/fmt/issues/4272,
|
||||
https://github.com/fmtlib/fmt/pull/4443,
|
||||
https://github.com/fmtlib/fmt/pull/4475).
|
||||
Thanks @nikhilreddydev and @localspook.
|
||||
|
||||
- Fix interaction between debug presentation, precision, and width for strings
|
||||
(https://github.com/fmtlib/fmt/pull/4478). Thanks @localspook.
|
||||
|
||||
- Implemented allocator propagation on `basic_memory_buffer` move
|
||||
(https://github.com/fmtlib/fmt/issues/4487,
|
||||
https://github.com/fmtlib/fmt/pull/4490). Thanks @toprakmurat.
|
||||
|
||||
- Fixed an ambiguity between `std::reference_wrapper<T>` and `format_as`
|
||||
formatters (https://github.com/fmtlib/fmt/issues/4424,
|
||||
https://github.com/fmtlib/fmt/pull/4434). Thanks @jeremy-rifkin.
|
||||
|
||||
- Removed the following deprecated APIs:
|
||||
|
||||
- `has_formatter`: use `is_formattable` instead,
|
||||
- `basic_format_args::parse_context_type`,
|
||||
`basic_format_args::formatter_type` and similar aliases in context types,
|
||||
- wide stream overload of `fmt::printf`,
|
||||
- wide stream overloads of `fmt::print` that take text styles,
|
||||
- `is_*char` traits,
|
||||
- `fmt::localtime`.
|
||||
|
||||
- Deprecated wide overloads of `fmt::fprintf` and `fmt::sprintf`.
|
||||
|
||||
- Improved diagnostics for the incorrect usage of `fmt::ptr`
|
||||
(https://github.com/fmtlib/fmt/pull/4453). Thanks @TobiSchluter.
|
||||
|
||||
- Made handling of ANSI escape sequences more efficient
|
||||
(https://github.com/fmtlib/fmt/pull/4511,
|
||||
https://github.com/fmtlib/fmt/pull/4528).
|
||||
Thanks @localspook and @Anas-Hamdane.
|
||||
|
||||
- Fixed a buffer overflow on all emphasis flags set
|
||||
(https://github.com/fmtlib/fmt/pull/4498). Thanks @dominicpoeschko.
|
||||
|
||||
- Fixed an integer overflow for precision close to the max `int` value.
|
||||
|
||||
- Fixed compatibility with WASI (https://github.com/fmtlib/fmt/issues/4496,
|
||||
https://github.com/fmtlib/fmt/pull/4497). Thanks @whitequark.
|
||||
|
||||
- Fixed `back_insert_iterator` detection, preventing a fallback on slower path
|
||||
that handles arbitrary iterators (https://github.com/fmtlib/fmt/issues/4454).
|
||||
|
||||
- Fixed handling of invalid glibc `FILE` buffers
|
||||
(https://github.com/fmtlib/fmt/issues/4469).
|
||||
|
||||
- Added `wchar_t` support to the `std::byte` formatter
|
||||
(https://github.com/fmtlib/fmt/issues/4479,
|
||||
https://github.com/fmtlib/fmt/pull/4480). Thanks @phprus.
|
||||
|
||||
- Changed component prefix from `fmt-` to `fmt_` for compatibility with
|
||||
NSIS/CPack on Windows, e.g. `fmt-doc` changed to `fmt_doc`
|
||||
(https://github.com/fmtlib/fmt/issues/4441,
|
||||
https://github.com/fmtlib/fmt/pull/4442). Thanks @n-stein.
|
||||
|
||||
- Added the `FMT_CUSTOM_ASSERT_FAIL` macro to simplify providing a custom
|
||||
`fmt::assert_fail` implementation (https://github.com/fmtlib/fmt/pull/4505).
|
||||
Thanks @HazardyKnusperkeks.
|
||||
|
||||
- Switched to `FMT_THROW` on reporting format errors so that it can be
|
||||
overriden by users when exceptions are disabled
|
||||
(https://github.com/fmtlib/fmt/pull/4521). Thanks @HazardyKnusperkeks.
|
||||
|
||||
- Improved master project detection and disabled install targets when using
|
||||
{fmt} as a subproject by default (https://github.com/fmtlib/fmt/pull/4536).
|
||||
Thanks @crueter.
|
||||
|
||||
- Made various code improvements
|
||||
(https://github.com/fmtlib/fmt/pull/4445,
|
||||
https://github.com/fmtlib/fmt/pull/4448,
|
||||
https://github.com/fmtlib/fmt/pull/4473,
|
||||
https://github.com/fmtlib/fmt/pull/4522).
|
||||
Thanks @localspook, @tchaikov and @way4sahil.
|
||||
|
||||
- Added Conan instructions to the docs
|
||||
(https://github.com/fmtlib/fmt/pull/4537). Thanks @uilianries.
|
||||
|
||||
- Removed Bazel files to avoid issues with downstream packaging
|
||||
(https://github.com/fmtlib/fmt/pull/4530). Thanks @mering.
|
||||
|
||||
- Added more entries for generated files to `.gitignore`
|
||||
(https://github.com/fmtlib/fmt/pull/4355,
|
||||
https://github.com/fmtlib/fmt/pull/4512).
|
||||
Thanks @dinomight and @localspook.
|
||||
|
||||
- Fixed various warnings and compilation issues
|
||||
(https://github.com/fmtlib/fmt/pull/4447,
|
||||
https://github.com/fmtlib/fmt/issues/4470,
|
||||
https://github.com/fmtlib/fmt/pull/4474,
|
||||
https://github.com/fmtlib/fmt/pull/4477,
|
||||
https://github.com/fmtlib/fmt/pull/4471,
|
||||
https://github.com/fmtlib/fmt/pull/4483,
|
||||
https://github.com/fmtlib/fmt/pull/4515,
|
||||
https://github.com/fmtlib/fmt/issues/4533,
|
||||
https://github.com/fmtlib/fmt/pull/4534).
|
||||
Thanks @dodomorandi, @localspook, @remyjette, @Tomek-Stolarczyk, @Mishura4,
|
||||
@mattiasljungstrom and @FatihBAKIR.
|
||||
|
||||
# 11.2.0 - 2025-05-03
|
||||
|
||||
- Added the `s` specifier for `std::error_code`. It allows formatting an error
|
||||
@@ -56,17 +229,18 @@
|
||||
https://github.com/fmtlib/fmt/pull/4361). Thanks @dinomight.
|
||||
|
||||
- Added error reporting for duplicate named arguments
|
||||
(https://github.com/fmtlib/fmt/pull/4367). Thanks @dinomight.
|
||||
(https://github.com/fmtlib/fmt/issues/4282,
|
||||
https://github.com/fmtlib/fmt/pull/4367). Thanks @dinomight.
|
||||
|
||||
- Fixed formatting of `long` with `FMT_BUILTIN_TYPES=0`
|
||||
(https://github.com/fmtlib/fmt/issues/4375,
|
||||
https://github.com/fmtlib/fmt/issues/4394).
|
||||
|
||||
- Optimized `text_style` using bit packing
|
||||
(https://github.com/fmtlib/fmt/pull/4363). Thanks @LocalSpook.
|
||||
(https://github.com/fmtlib/fmt/pull/4363). Thanks @localspook.
|
||||
|
||||
- Added support for incomplete types (https://github.com/fmtlib/fmt/issues/3180,
|
||||
https://github.com/fmtlib/fmt/pull/4383). Thanks @LocalSpook.
|
||||
https://github.com/fmtlib/fmt/pull/4383). Thanks @localspook.
|
||||
|
||||
- Fixed a flush issue in `fmt::print` when using libstdc++
|
||||
(https://github.com/fmtlib/fmt/issues/4398).
|
||||
@@ -107,13 +281,14 @@
|
||||
`float` (https://github.com/fmtlib/fmt/issues/3649).
|
||||
|
||||
- Moved `is_compiled_string` to the public API
|
||||
(https://github.com/fmtlib/fmt/issues/4342). Thanks @SwooshyCueb.
|
||||
(https://github.com/fmtlib/fmt/issues/4335,
|
||||
https://github.com/fmtlib/fmt/issues/4342). Thanks @SwooshyCueb.
|
||||
|
||||
- Simplified implementation of `operator""_cf`
|
||||
(https://github.com/fmtlib/fmt/pull/4349). Thanks @LocalSpook.
|
||||
(https://github.com/fmtlib/fmt/pull/4349). Thanks @localspook.
|
||||
|
||||
- Fixed `__builtin_strlen` detection (https://github.com/fmtlib/fmt/pull/4329).
|
||||
Thanks @LocalSpook.
|
||||
Thanks @localspook.
|
||||
|
||||
- Fixed handling of BMI paths with the Ninja generator
|
||||
(https://github.com/fmtlib/fmt/pull/4344). Thanks @tkhyn.
|
||||
|
||||
3
3rdparty/fmt/README.md
vendored
3
3rdparty/fmt/README.md
vendored
@@ -4,8 +4,9 @@
|
||||
[](https://github.com/fmtlib/fmt/actions?query=workflow%3Amacos)
|
||||
[](https://github.com/fmtlib/fmt/actions?query=workflow%3Awindows)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?\%0Acolspec=ID%20Type%20Component%20Status%20Proj%20Reported%20Owner%20\%0ASummary&q=proj%3Dfmt&can=1)
|
||||
[](https://stackoverflow.com/questions/tagged/fmt)
|
||||
[](https://www.bestpractices.dev/projects/8880)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/fmtlib/fmt)
|
||||
[](https://stackoverflow.com/questions/tagged/fmt)
|
||||
|
||||
**{fmt}** is an open-source formatting library providing a fast and safe
|
||||
alternative to C stdio and C++ iostreams.
|
||||
|
||||
4
3rdparty/fmt/include/fmt/args.h
vendored
4
3rdparty/fmt/include/fmt/args.h
vendored
@@ -71,7 +71,7 @@ class dynamic_arg_list {
|
||||
* It can be implicitly converted into `fmt::basic_format_args` for passing
|
||||
* into type-erased formatting functions such as `fmt::vformat`.
|
||||
*/
|
||||
template <typename Context> class dynamic_format_arg_store {
|
||||
FMT_EXPORT template <typename Context> class dynamic_format_arg_store {
|
||||
private:
|
||||
using char_type = typename Context::char_type;
|
||||
|
||||
@@ -212,7 +212,7 @@ template <typename Context> class dynamic_format_arg_store {
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the store.
|
||||
size_t size() const noexcept { return data_.size(); }
|
||||
auto size() const noexcept -> size_t { return data_.size(); }
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
179
3rdparty/fmt/include/fmt/base.h
vendored
179
3rdparty/fmt/include/fmt/base.h
vendored
@@ -21,7 +21,7 @@
|
||||
#endif
|
||||
|
||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||
#define FMT_VERSION 110200
|
||||
#define FMT_VERSION 120000
|
||||
|
||||
// Detect compiler versions.
|
||||
#if defined(__clang__) && !defined(__ibmxl__)
|
||||
@@ -201,14 +201,6 @@
|
||||
# define FMT_NODISCARD
|
||||
#endif
|
||||
|
||||
#ifdef FMT_DEPRECATED
|
||||
// Use the provided definition.
|
||||
#elif FMT_HAS_CPP14_ATTRIBUTE(deprecated)
|
||||
# define FMT_DEPRECATED [[deprecated]]
|
||||
#else
|
||||
# define FMT_DEPRECATED /* deprecated */
|
||||
#endif
|
||||
|
||||
#if FMT_GCC_VERSION || FMT_CLANG_VERSION
|
||||
# define FMT_VISIBILITY(value) __attribute__((visibility(value)))
|
||||
#else
|
||||
@@ -260,7 +252,7 @@ FMT_PRAGMA_CLANG(diagnostic push)
|
||||
#ifndef FMT_BEGIN_NAMESPACE
|
||||
# define FMT_BEGIN_NAMESPACE \
|
||||
namespace fmt { \
|
||||
inline namespace v11 {
|
||||
inline namespace v12 {
|
||||
# define FMT_END_NAMESPACE \
|
||||
} \
|
||||
}
|
||||
@@ -356,6 +348,9 @@ template <typename T> constexpr auto max_of(T a, T b) -> T {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
|
||||
const char* message);
|
||||
|
||||
namespace detail {
|
||||
// Suppresses "unused variable" warnings with the method described in
|
||||
// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
|
||||
@@ -396,7 +391,7 @@ FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
|
||||
# define FMT_ASSERT(condition, message) \
|
||||
((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
|
||||
? (void)0 \
|
||||
: fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
|
||||
: ::fmt::assert_fail(__FILE__, __LINE__, (message)))
|
||||
#endif
|
||||
|
||||
#ifdef FMT_USE_INT128
|
||||
@@ -463,12 +458,13 @@ enum { use_utf8 = !FMT_WIN32 || is_utf8_enabled };
|
||||
static_assert(!FMT_UNICODE || use_utf8,
|
||||
"Unicode support requires compiling with /utf-8");
|
||||
|
||||
template <typename T> constexpr const char* narrow(const T*) { return nullptr; }
|
||||
constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; }
|
||||
template <typename T> constexpr auto narrow(T*) -> char* { return nullptr; }
|
||||
constexpr FMT_ALWAYS_INLINE auto narrow(const char* s) -> const char* {
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n)
|
||||
-> int {
|
||||
FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, size_t n) -> int {
|
||||
if (!is_constant_evaluated() && sizeof(Char) == 1) return memcmp(s1, s2, n);
|
||||
for (; n != 0; ++s1, ++s2, --n) {
|
||||
if (*s1 < *s2) return -1;
|
||||
@@ -540,7 +536,7 @@ template <typename Char> class basic_string_view {
|
||||
FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s) {
|
||||
#if FMT_HAS_BUILTIN(__builtin_strlen) || FMT_GCC_VERSION || FMT_CLANG_VERSION
|
||||
if (std::is_same<Char, char>::value && !detail::is_constant_evaluated()) {
|
||||
size_ = __builtin_strlen(detail::narrow(s)); // strlen is not costexpr.
|
||||
size_ = __builtin_strlen(detail::narrow(s)); // strlen is not constexpr.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -616,19 +612,6 @@ template <typename Char> class basic_string_view {
|
||||
|
||||
using string_view = basic_string_view<char>;
|
||||
|
||||
// DEPRECATED! Will be merged with is_char and moved to detail.
|
||||
template <typename T> struct is_xchar : std::false_type {};
|
||||
template <> struct is_xchar<wchar_t> : std::true_type {};
|
||||
template <> struct is_xchar<char16_t> : std::true_type {};
|
||||
template <> struct is_xchar<char32_t> : std::true_type {};
|
||||
#ifdef __cpp_char8_t
|
||||
template <> struct is_xchar<char8_t> : std::true_type {};
|
||||
#endif
|
||||
|
||||
// Specifies if `T` is a character (code unit) type.
|
||||
template <typename T> struct is_char : is_xchar<T> {};
|
||||
template <> struct is_char<char> : std::true_type {};
|
||||
|
||||
template <typename T> class basic_appender;
|
||||
using appender = basic_appender<char>;
|
||||
|
||||
@@ -781,7 +764,7 @@ class basic_specs {
|
||||
(static_cast<unsigned>(p) << precision_shift);
|
||||
}
|
||||
|
||||
constexpr bool dynamic() const {
|
||||
constexpr auto dynamic() const -> bool {
|
||||
return (data_ & (width_mask | precision_mask)) != 0;
|
||||
}
|
||||
|
||||
@@ -921,14 +904,47 @@ template <typename Char = char> class parse_context {
|
||||
FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
|
||||
};
|
||||
|
||||
#ifndef FMT_USE_LOCALE
|
||||
# define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1)
|
||||
#endif
|
||||
|
||||
// A type-erased reference to std::locale to avoid the heavy <locale> include.
|
||||
class locale_ref {
|
||||
#if FMT_USE_LOCALE
|
||||
private:
|
||||
const void* locale_; // A type-erased pointer to std::locale.
|
||||
|
||||
public:
|
||||
constexpr locale_ref() : locale_(nullptr) {}
|
||||
|
||||
template <typename Locale, FMT_ENABLE_IF(sizeof(Locale::collate) != 0)>
|
||||
locale_ref(const Locale& loc);
|
||||
|
||||
inline explicit operator bool() const noexcept { return locale_ != nullptr; }
|
||||
#endif // FMT_USE_LOCALE
|
||||
|
||||
public:
|
||||
template <typename Locale> auto get() const -> Locale;
|
||||
};
|
||||
|
||||
FMT_END_EXPORT
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Specifies if `T` is a code unit type.
|
||||
template <typename T> struct is_code_unit : std::false_type {};
|
||||
template <> struct is_code_unit<char> : std::true_type {};
|
||||
template <> struct is_code_unit<wchar_t> : std::true_type {};
|
||||
template <> struct is_code_unit<char16_t> : std::true_type {};
|
||||
template <> struct is_code_unit<char32_t> : std::true_type {};
|
||||
#ifdef __cpp_char8_t
|
||||
template <> struct is_code_unit<char8_t> : bool_constant<is_utf8_enabled> {};
|
||||
#endif
|
||||
|
||||
// Constructs fmt::basic_string_view<Char> from types implicitly convertible
|
||||
// to it, deducing Char. Explicitly convertible types such as the ones returned
|
||||
// from FMT_STRING are intentionally excluded.
|
||||
template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
|
||||
template <typename Char, FMT_ENABLE_IF(is_code_unit<Char>::value)>
|
||||
constexpr auto to_string_view(const Char* s) -> basic_string_view<Char> {
|
||||
return s;
|
||||
}
|
||||
@@ -1057,11 +1073,11 @@ template <bool B1, bool B2, bool... Tail> constexpr auto count() -> int {
|
||||
return (B1 ? 1 : 0) + count<B2, Tail...>();
|
||||
}
|
||||
|
||||
template <typename... Args> constexpr auto count_named_args() -> int {
|
||||
return count<is_named_arg<Args>::value...>();
|
||||
template <typename... T> constexpr auto count_named_args() -> int {
|
||||
return count<is_named_arg<T>::value...>();
|
||||
}
|
||||
template <typename... Args> constexpr auto count_static_named_args() -> int {
|
||||
return count<is_static_named_arg<Args>::value...>();
|
||||
template <typename... T> constexpr auto count_static_named_args() -> int {
|
||||
return count<is_static_named_arg<T>::value...>();
|
||||
}
|
||||
|
||||
template <typename Char> struct named_arg_info {
|
||||
@@ -1069,7 +1085,7 @@ template <typename Char> struct named_arg_info {
|
||||
int id;
|
||||
};
|
||||
|
||||
// named_args is non-const to suppress a bogus -Wmaybe-uninitalized in gcc 13.
|
||||
// named_args is non-const to suppress a bogus -Wmaybe-uninitialized in gcc 13.
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR void check_for_duplicate(named_arg_info<Char>* named_args,
|
||||
int named_arg_index,
|
||||
@@ -1173,7 +1189,7 @@ template <typename Char> struct type_mapper {
|
||||
static auto map(ubitint<N>)
|
||||
-> conditional_t<N <= 64, unsigned long long, void>;
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(is_char<T>::value)>
|
||||
template <typename T, FMT_ENABLE_IF(is_code_unit<T>::value)>
|
||||
static auto map(T) -> conditional_t<
|
||||
std::is_same<T, char>::value || std::is_same<T, Char>::value, Char, void>;
|
||||
|
||||
@@ -1679,12 +1695,12 @@ template <typename... T> struct arg_pack {};
|
||||
template <typename Char, int NUM_ARGS, int NUM_NAMED_ARGS, bool DYNAMIC_NAMES>
|
||||
class format_string_checker {
|
||||
private:
|
||||
type types_[max_of(1, NUM_ARGS)];
|
||||
named_arg_info<Char> named_args_[max_of(1, NUM_NAMED_ARGS)];
|
||||
type types_[max_of<size_t>(1, NUM_ARGS)];
|
||||
named_arg_info<Char> named_args_[max_of<size_t>(1, NUM_NAMED_ARGS)];
|
||||
compile_parse_context<Char> context_;
|
||||
|
||||
using parse_func = auto (*)(parse_context<Char>&) -> const Char*;
|
||||
parse_func parse_funcs_[max_of(1, NUM_ARGS)];
|
||||
parse_func parse_funcs_[max_of<size_t>(1, NUM_ARGS)];
|
||||
|
||||
public:
|
||||
template <typename... T>
|
||||
@@ -2033,6 +2049,17 @@ struct has_back_insert_iterator_container_append<
|
||||
.append(std::declval<InputIt>(),
|
||||
std::declval<InputIt>()))>> : std::true_type {};
|
||||
|
||||
template <typename OutputIt, typename InputIt, typename = void>
|
||||
struct has_back_insert_iterator_container_insert_at_end : std::false_type {};
|
||||
|
||||
template <typename OutputIt, typename InputIt>
|
||||
struct has_back_insert_iterator_container_insert_at_end<
|
||||
OutputIt, InputIt,
|
||||
void_t<decltype(get_container(std::declval<OutputIt>())
|
||||
.insert(get_container(std::declval<OutputIt>()).end(),
|
||||
std::declval<InputIt>(),
|
||||
std::declval<InputIt>()))>> : std::true_type {};
|
||||
|
||||
// An optimized version of std::copy with the output value type (T).
|
||||
template <typename T, typename InputIt, typename OutputIt,
|
||||
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
|
||||
@@ -2047,6 +2074,8 @@ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
|
||||
template <typename T, typename InputIt, typename OutputIt,
|
||||
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value &&
|
||||
!has_back_insert_iterator_container_append<
|
||||
OutputIt, InputIt>::value &&
|
||||
has_back_insert_iterator_container_insert_at_end<
|
||||
OutputIt, InputIt>::value)>
|
||||
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
|
||||
-> OutputIt {
|
||||
@@ -2056,7 +2085,11 @@ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out)
|
||||
}
|
||||
|
||||
template <typename T, typename InputIt, typename OutputIt,
|
||||
FMT_ENABLE_IF(!is_back_insert_iterator<OutputIt>::value)>
|
||||
FMT_ENABLE_IF(!(is_back_insert_iterator<OutputIt>::value &&
|
||||
(has_back_insert_iterator_container_append<
|
||||
OutputIt, InputIt>::value ||
|
||||
has_back_insert_iterator_container_insert_at_end<
|
||||
OutputIt, InputIt>::value)))>
|
||||
FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt {
|
||||
while (begin != end) *out++ = static_cast<T>(*begin++);
|
||||
return out;
|
||||
@@ -2176,7 +2209,7 @@ template <typename Context> class value {
|
||||
static_assert(N <= 64, "unsupported _BitInt");
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(is_char<T>::value)>
|
||||
template <typename T, FMT_ENABLE_IF(is_code_unit<T>::value)>
|
||||
constexpr FMT_INLINE value(T x FMT_BUILTIN) : char_value(x) {
|
||||
static_assert(
|
||||
std::is_same<T, char>::value || std::is_same<T, char_type>::value,
|
||||
@@ -2252,7 +2285,7 @@ template <typename Context> class value {
|
||||
custom.value = const_cast<value_type*>(&x);
|
||||
#endif
|
||||
}
|
||||
custom.format = format_custom<value_type, formatter<value_type, char_type>>;
|
||||
custom.format = format_custom<value_type>;
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!has_formatter<T, char_type>())>
|
||||
@@ -2263,10 +2296,10 @@ template <typename Context> class value {
|
||||
}
|
||||
|
||||
// Formats an argument of a custom type, such as a user-defined class.
|
||||
template <typename T, typename Formatter>
|
||||
template <typename T>
|
||||
static void format_custom(void* arg, parse_context<char_type>& parse_ctx,
|
||||
Context& ctx) {
|
||||
auto f = Formatter();
|
||||
auto f = formatter<T, char_type>();
|
||||
parse_ctx.advance_to(f.parse(parse_ctx));
|
||||
using qualified_type =
|
||||
conditional_t<has_formatter<const T, char_type>(), const T, T>;
|
||||
@@ -2293,35 +2326,14 @@ struct is_output_iterator<
|
||||
enable_if_t<std::is_assignable<decltype(*std::declval<decay_t<It>&>()++),
|
||||
T>::value>> : std::true_type {};
|
||||
|
||||
#ifndef FMT_USE_LOCALE
|
||||
# define FMT_USE_LOCALE (FMT_OPTIMIZE_SIZE <= 1)
|
||||
#endif
|
||||
|
||||
// A type-erased reference to an std::locale to avoid a heavy <locale> include.
|
||||
class locale_ref {
|
||||
#if FMT_USE_LOCALE
|
||||
private:
|
||||
const void* locale_; // A type-erased pointer to std::locale.
|
||||
|
||||
public:
|
||||
constexpr locale_ref() : locale_(nullptr) {}
|
||||
template <typename Locale> locale_ref(const Locale& loc);
|
||||
|
||||
inline explicit operator bool() const noexcept { return locale_ != nullptr; }
|
||||
#endif // FMT_USE_LOCALE
|
||||
|
||||
public:
|
||||
template <typename Locale> auto get() const -> Locale;
|
||||
};
|
||||
|
||||
template <typename> constexpr auto encode_types() -> unsigned long long {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Context, typename Arg, typename... Args>
|
||||
template <typename Context, typename First, typename... T>
|
||||
constexpr auto encode_types() -> unsigned long long {
|
||||
return static_cast<unsigned>(stored_type_constant<Arg, Context>::value) |
|
||||
(encode_types<Context, Args...>() << packed_arg_bits);
|
||||
return static_cast<unsigned>(stored_type_constant<First, Context>::value) |
|
||||
(encode_types<Context, T...>() << packed_arg_bits);
|
||||
}
|
||||
|
||||
template <typename Context, typename... T, size_t NUM_ARGS = sizeof...(T)>
|
||||
@@ -2338,8 +2350,9 @@ template <typename Context, int NUM_ARGS, int NUM_NAMED_ARGS,
|
||||
unsigned long long DESC>
|
||||
struct named_arg_store {
|
||||
// args_[0].named_args points to named_args to avoid bloating format_args.
|
||||
arg_t<Context, NUM_ARGS> args[1 + NUM_ARGS];
|
||||
named_arg_info<typename Context::char_type> named_args[NUM_NAMED_ARGS];
|
||||
arg_t<Context, NUM_ARGS> args[1u + NUM_ARGS];
|
||||
named_arg_info<typename Context::char_type>
|
||||
named_args[static_cast<size_t>(NUM_NAMED_ARGS)];
|
||||
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR FMT_ALWAYS_INLINE named_arg_store(T&... values)
|
||||
@@ -2358,8 +2371,8 @@ struct named_arg_store {
|
||||
}
|
||||
|
||||
named_arg_store(const named_arg_store& rhs) = delete;
|
||||
named_arg_store& operator=(const named_arg_store& rhs) = delete;
|
||||
named_arg_store& operator=(named_arg_store&& rhs) = delete;
|
||||
auto operator=(const named_arg_store& rhs) -> named_arg_store& = delete;
|
||||
auto operator=(named_arg_store&& rhs) -> named_arg_store& = delete;
|
||||
operator const arg_t<Context, NUM_ARGS>*() const { return args + 1; }
|
||||
};
|
||||
|
||||
@@ -2372,7 +2385,7 @@ struct format_arg_store {
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
using type =
|
||||
conditional_t<NUM_NAMED_ARGS == 0,
|
||||
arg_t<Context, NUM_ARGS>[max_of(1, NUM_ARGS)],
|
||||
arg_t<Context, NUM_ARGS>[max_of<size_t>(1, NUM_ARGS)],
|
||||
named_arg_store<Context, NUM_ARGS, NUM_NAMED_ARGS, DESC>>;
|
||||
type args;
|
||||
};
|
||||
@@ -2656,22 +2669,17 @@ class context {
|
||||
private:
|
||||
appender out_;
|
||||
format_args args_;
|
||||
FMT_NO_UNIQUE_ADDRESS detail::locale_ref loc_;
|
||||
FMT_NO_UNIQUE_ADDRESS locale_ref loc_;
|
||||
|
||||
public:
|
||||
/// The character type for the output.
|
||||
using char_type = char;
|
||||
|
||||
using char_type = char; ///< The character type for the output.
|
||||
using iterator = appender;
|
||||
using format_arg = basic_format_arg<context>;
|
||||
using parse_context_type FMT_DEPRECATED = parse_context<>;
|
||||
template <typename T> using formatter_type FMT_DEPRECATED = formatter<T>;
|
||||
enum { builtin_types = FMT_BUILTIN_TYPES };
|
||||
|
||||
/// Constructs a `context` object. References to the arguments are stored
|
||||
/// in the object so make sure they have appropriate lifetimes.
|
||||
FMT_CONSTEXPR context(iterator out, format_args args,
|
||||
detail::locale_ref loc = {})
|
||||
FMT_CONSTEXPR context(iterator out, format_args args, locale_ref loc = {})
|
||||
: out_(out), args_(args), loc_(loc) {}
|
||||
context(context&&) = default;
|
||||
context(const context&) = delete;
|
||||
@@ -2692,7 +2700,7 @@ class context {
|
||||
// Advances the begin iterator to `it`.
|
||||
FMT_CONSTEXPR void advance_to(iterator) {}
|
||||
|
||||
FMT_CONSTEXPR auto locale() const -> detail::locale_ref { return loc_; }
|
||||
FMT_CONSTEXPR auto locale() const -> locale_ref { return loc_; }
|
||||
};
|
||||
|
||||
template <typename Char = char> struct runtime_format_string {
|
||||
@@ -2779,9 +2787,6 @@ template <typename T, typename Char = char>
|
||||
concept formattable = is_formattable<remove_reference_t<T>, Char>::value;
|
||||
#endif
|
||||
|
||||
template <typename T, typename Char>
|
||||
using has_formatter FMT_DEPRECATED = std::is_constructible<formatter<T, Char>>;
|
||||
|
||||
// A formatter specialization for natively supported types.
|
||||
template <typename T, typename Char>
|
||||
struct formatter<T, Char,
|
||||
@@ -2978,9 +2983,9 @@ FMT_INLINE void println(format_string<T...> fmt, T&&... args) {
|
||||
return fmt::println(stdout, fmt, static_cast<T&&>(args)...);
|
||||
}
|
||||
|
||||
FMT_END_EXPORT
|
||||
FMT_PRAGMA_CLANG(diagnostic pop)
|
||||
FMT_PRAGMA_GCC(pop_options)
|
||||
FMT_END_EXPORT
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
|
||||
113
3rdparty/fmt/include/fmt/chrono.h
vendored
113
3rdparty/fmt/include/fmt/chrono.h
vendored
@@ -38,6 +38,7 @@ FMT_BEGIN_NAMESPACE
|
||||
// Copyright Paul Dreik 2019
|
||||
namespace safe_duration_cast {
|
||||
|
||||
// DEPRECATED!
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(!std::is_same<From, To>::value &&
|
||||
std::numeric_limits<From>::is_signed ==
|
||||
@@ -161,17 +162,6 @@ auto safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
int& ec) -> To {
|
||||
using From = std::chrono::duration<FromRep, FromPeriod>;
|
||||
ec = 0;
|
||||
if (std::isnan(from.count())) {
|
||||
// nan in, gives nan out. easy.
|
||||
return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
|
||||
}
|
||||
// maybe we should also check if from is denormal, and decide what to do about
|
||||
// it.
|
||||
|
||||
// +-inf should be preserved.
|
||||
if (std::isinf(from.count())) {
|
||||
return To{from.count()};
|
||||
}
|
||||
|
||||
// the basic idea is that we need to convert from count() in the from type
|
||||
// to count() in the To type, by multiplying it with this:
|
||||
@@ -282,8 +272,6 @@ namespace detail {
|
||||
#define FMT_NOMACRO
|
||||
|
||||
template <typename T = void> struct null {};
|
||||
inline auto localtime_r FMT_NOMACRO(...) -> null<> { return null<>(); }
|
||||
inline auto localtime_s(...) -> null<> { return null<>(); }
|
||||
inline auto gmtime_r(...) -> null<> { return null<>(); }
|
||||
inline auto gmtime_s(...) -> null<> { return null<>(); }
|
||||
|
||||
@@ -326,7 +314,7 @@ inline auto get_classic_locale() -> const std::locale& {
|
||||
}
|
||||
|
||||
template <typename CodeUnit> struct codecvt_result {
|
||||
static constexpr const size_t max_size = 32;
|
||||
static constexpr size_t max_size = 32;
|
||||
CodeUnit buf[max_size];
|
||||
CodeUnit* end;
|
||||
};
|
||||
@@ -443,11 +431,7 @@ auto duration_cast(std::chrono::duration<FromRep, FromPeriod> from) -> To {
|
||||
|
||||
using common_rep = typename std::common_type<FromRep, typename To::rep,
|
||||
decltype(factor::num)>::type;
|
||||
|
||||
int ec = 0;
|
||||
auto count = safe_duration_cast::lossless_integral_conversion<common_rep>(
|
||||
from.count(), ec);
|
||||
if (ec) throw_duration_error();
|
||||
common_rep count = from.count(); // This conversion is lossless.
|
||||
|
||||
// Multiply from.count() by factor and check for overflow.
|
||||
if (const_check(factor::num != 1)) {
|
||||
@@ -458,6 +442,7 @@ auto duration_cast(std::chrono::duration<FromRep, FromPeriod> from) -> To {
|
||||
count *= factor::num;
|
||||
}
|
||||
if (const_check(factor::den != 1)) count /= factor::den;
|
||||
int ec = 0;
|
||||
auto to =
|
||||
To(safe_duration_cast::lossless_integral_conversion<typename To::rep>(
|
||||
count, ec));
|
||||
@@ -471,6 +456,8 @@ template <typename To, typename FromRep, typename FromPeriod,
|
||||
std::is_floating_point<typename To::rep>::value)>
|
||||
auto duration_cast(std::chrono::duration<FromRep, FromPeriod> from) -> To {
|
||||
#if FMT_SAFE_DURATION_CAST
|
||||
// Preserve infinity and NaN.
|
||||
if (!isfinite(from.count())) return static_cast<To>(from.count());
|
||||
// Throwing version of safe_duration_cast is only available for
|
||||
// integer to integer or float to float casts.
|
||||
int ec;
|
||||
@@ -487,7 +474,7 @@ template <typename To, typename FromRep, typename FromPeriod,
|
||||
FMT_ENABLE_IF(
|
||||
!is_similar_arithmetic_type<FromRep, typename To::rep>::value)>
|
||||
auto duration_cast(std::chrono::duration<FromRep, FromPeriod> from) -> To {
|
||||
// Mixed integer <-> float cast is not supported by safe_duration_cast.
|
||||
// Mixed integer <-> float cast is not supported by safe duration_cast.
|
||||
return std::chrono::duration_cast<To>(from);
|
||||
}
|
||||
|
||||
@@ -501,86 +488,10 @@ auto to_time_t(sys_time<Duration> time_point) -> std::time_t {
|
||||
.count();
|
||||
}
|
||||
|
||||
namespace tz {
|
||||
|
||||
// DEPRECATED!
|
||||
struct time_zone {
|
||||
template <typename Duration, typename LocalTime>
|
||||
auto to_sys(LocalTime) -> sys_time<Duration> {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
template <typename... T> auto current_zone(T...) -> time_zone* {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename... T> void _tzset(T...) {}
|
||||
} // namespace tz
|
||||
|
||||
// DEPRECATED!
|
||||
inline void tzset_once() {
|
||||
static bool init = []() {
|
||||
using namespace tz;
|
||||
_tzset();
|
||||
return false;
|
||||
}();
|
||||
ignore_unused(init);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
/**
|
||||
* Converts given time since epoch as `std::time_t` value into calendar time,
|
||||
* expressed in local time. Unlike `std::localtime`, this function is
|
||||
* thread-safe on most platforms.
|
||||
*/
|
||||
FMT_DEPRECATED inline auto localtime(std::time_t time) -> std::tm {
|
||||
struct dispatcher {
|
||||
std::time_t time_;
|
||||
std::tm tm_;
|
||||
|
||||
inline dispatcher(std::time_t t) : time_(t) {}
|
||||
|
||||
inline auto run() -> bool {
|
||||
using namespace fmt::detail;
|
||||
return handle(localtime_r(&time_, &tm_));
|
||||
}
|
||||
|
||||
inline auto handle(std::tm* tm) -> bool { return tm != nullptr; }
|
||||
|
||||
inline auto handle(detail::null<>) -> bool {
|
||||
using namespace fmt::detail;
|
||||
return fallback(localtime_s(&tm_, &time_));
|
||||
}
|
||||
|
||||
inline auto fallback(int res) -> bool { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VERSION
|
||||
inline auto fallback(detail::null<>) -> bool {
|
||||
using namespace fmt::detail;
|
||||
std::tm* tm = std::localtime(&time_);
|
||||
if (tm) tm_ = *tm;
|
||||
return tm != nullptr;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
dispatcher lt(time);
|
||||
// Too big time values may be unsupported.
|
||||
if (!lt.run()) FMT_THROW(format_error("time_t value out of range"));
|
||||
return lt.tm_;
|
||||
}
|
||||
|
||||
#if FMT_USE_LOCAL_TIME
|
||||
template <typename Duration>
|
||||
FMT_DEPRECATED auto localtime(std::chrono::local_time<Duration> time)
|
||||
-> std::tm {
|
||||
using namespace std::chrono;
|
||||
using namespace detail::tz;
|
||||
return localtime(detail::to_time_t(current_zone()->to_sys<Duration>(time)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts given time since epoch as `std::time_t` value into calendar time,
|
||||
* expressed in Coordinated Universal Time (UTC). Unlike `std::gmtime`, this
|
||||
@@ -652,7 +563,7 @@ inline void write_digit2_separated(char* buf, unsigned a, unsigned b,
|
||||
// Add ASCII '0' to each digit byte and insert separators.
|
||||
digits |= 0x3030003030003030 | (usep << 16) | (usep << 40);
|
||||
|
||||
constexpr const size_t len = 8;
|
||||
constexpr size_t len = 8;
|
||||
if (const_check(is_big_endian())) {
|
||||
char tmp[len];
|
||||
std::memcpy(tmp, &digits, len);
|
||||
@@ -1000,16 +911,16 @@ template <typename T>
|
||||
struct has_tm_zone<T, void_t<decltype(T::tm_zone)>> : std::true_type {};
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(has_tm_zone<T>::value)>
|
||||
bool set_tm_zone(T& time, char* tz) {
|
||||
auto set_tm_zone(T& time, char* tz) -> bool {
|
||||
time.tm_zone = tz;
|
||||
return true;
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(!has_tm_zone<T>::value)>
|
||||
bool set_tm_zone(T&, char*) {
|
||||
auto set_tm_zone(T&, char*) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline char* utc() {
|
||||
inline auto utc() -> char* {
|
||||
static char tz[] = "UTC";
|
||||
return tz;
|
||||
}
|
||||
@@ -2230,7 +2141,7 @@ template <typename Char> struct formatter<std::tm, Char> {
|
||||
detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
|
||||
ctx);
|
||||
|
||||
auto loc_ref = specs.localized() ? ctx.locale() : detail::locale_ref();
|
||||
auto loc_ref = specs.localized() ? ctx.locale() : locale_ref();
|
||||
detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
|
||||
auto w = detail::tm_writer<basic_appender<Char>, Char, Duration>(
|
||||
loc, out, tm, subsecs);
|
||||
|
||||
36
3rdparty/fmt/include/fmt/color.h
vendored
36
3rdparty/fmt/include/fmt/color.h
vendored
@@ -375,19 +375,17 @@ template <typename Char> struct ansi_color_escape {
|
||||
// 10 more.
|
||||
if (is_background) value += 10u;
|
||||
|
||||
size_t index = 0;
|
||||
buffer[index++] = static_cast<Char>('\x1b');
|
||||
buffer[index++] = static_cast<Char>('[');
|
||||
buffer[size++] = static_cast<Char>('\x1b');
|
||||
buffer[size++] = static_cast<Char>('[');
|
||||
|
||||
if (value >= 100u) {
|
||||
buffer[index++] = static_cast<Char>('1');
|
||||
buffer[size++] = static_cast<Char>('1');
|
||||
value %= 100u;
|
||||
}
|
||||
buffer[index++] = static_cast<Char>('0' + value / 10u);
|
||||
buffer[index++] = static_cast<Char>('0' + value % 10u);
|
||||
buffer[size++] = static_cast<Char>('0' + value / 10u);
|
||||
buffer[size++] = static_cast<Char>('0' + value % 10u);
|
||||
|
||||
buffer[index++] = static_cast<Char>('m');
|
||||
buffer[index++] = static_cast<Char>('\0');
|
||||
buffer[size++] = static_cast<Char>('m');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -398,7 +396,7 @@ template <typename Char> struct ansi_color_escape {
|
||||
to_esc(color.r, buffer + 7, ';');
|
||||
to_esc(color.g, buffer + 11, ';');
|
||||
to_esc(color.b, buffer + 15, 'm');
|
||||
buffer[19] = static_cast<Char>(0);
|
||||
size = 19;
|
||||
}
|
||||
FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept {
|
||||
uint8_t em_codes[num_emphases] = {};
|
||||
@@ -411,26 +409,28 @@ template <typename Char> struct ansi_color_escape {
|
||||
if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8;
|
||||
if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9;
|
||||
|
||||
size_t index = 0;
|
||||
buffer[size++] = static_cast<Char>('\x1b');
|
||||
buffer[size++] = static_cast<Char>('[');
|
||||
|
||||
for (size_t i = 0; i < num_emphases; ++i) {
|
||||
if (!em_codes[i]) continue;
|
||||
buffer[index++] = static_cast<Char>('\x1b');
|
||||
buffer[index++] = static_cast<Char>('[');
|
||||
buffer[index++] = static_cast<Char>('0' + em_codes[i]);
|
||||
buffer[index++] = static_cast<Char>('m');
|
||||
buffer[size++] = static_cast<Char>('0' + em_codes[i]);
|
||||
buffer[size++] = static_cast<Char>(';');
|
||||
}
|
||||
buffer[index++] = static_cast<Char>(0);
|
||||
|
||||
buffer[size - 1] = static_cast<Char>('m');
|
||||
}
|
||||
FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; }
|
||||
|
||||
FMT_CONSTEXPR auto begin() const noexcept -> const Char* { return buffer; }
|
||||
FMT_CONSTEXPR20 auto end() const noexcept -> const Char* {
|
||||
return buffer + basic_string_view<Char>(buffer).size();
|
||||
FMT_CONSTEXPR auto end() const noexcept -> const Char* {
|
||||
return buffer + size;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t num_emphases = 8;
|
||||
Char buffer[7u + 3u * num_emphases + 1u];
|
||||
Char buffer[7u + 4u * num_emphases];
|
||||
size_t size = 0;
|
||||
|
||||
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
|
||||
char delimiter) noexcept {
|
||||
|
||||
198
3rdparty/fmt/include/fmt/compile.h
vendored
198
3rdparty/fmt/include/fmt/compile.h
vendored
@@ -22,8 +22,6 @@ FMT_EXPORT class compiled_string {};
|
||||
template <typename S>
|
||||
struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Converts a string literal `s` into a format string that will be parsed at
|
||||
* compile time and converted into efficient formatting code. Requires C++17
|
||||
@@ -41,18 +39,40 @@ namespace detail {
|
||||
# define FMT_COMPILE(s) FMT_STRING(s)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts a string literal into a format string that will be parsed at
|
||||
* compile time and converted into efficient formatting code. Requires support
|
||||
* for class types in constant template parameters (a C++20 feature).
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* // Converts 42 into std::string using the most efficient method and no
|
||||
* // runtime format string processing.
|
||||
* using namespace fmt::literals;
|
||||
* std::string s = fmt::format("{}"_cf, 42);
|
||||
*/
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
inline namespace literals {
|
||||
template <detail::fixed_string Str> constexpr auto operator""_cf() {
|
||||
return FMT_COMPILE(Str.data);
|
||||
}
|
||||
} // namespace literals
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename... Tail>
|
||||
auto first(const T& value, const Tail&...) -> const T& {
|
||||
constexpr auto first(const T& value, const Tail&...) -> const T& {
|
||||
return value;
|
||||
}
|
||||
|
||||
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
|
||||
template <typename... Args> struct type_list {};
|
||||
template <typename... T> struct type_list {};
|
||||
|
||||
// Returns a reference to the argument at index N from [first, rest...].
|
||||
template <int N, typename T, typename... Args>
|
||||
constexpr const auto& get([[maybe_unused]] const T& first,
|
||||
[[maybe_unused]] const Args&... rest) {
|
||||
constexpr auto get([[maybe_unused]] const T& first,
|
||||
[[maybe_unused]] const Args&... rest) -> const auto& {
|
||||
static_assert(N < 1 + sizeof...(Args), "index is out of bounds");
|
||||
if constexpr (N == 0)
|
||||
return first;
|
||||
@@ -84,8 +104,8 @@ FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
|
||||
}
|
||||
|
||||
template <typename Char, typename... Args>
|
||||
constexpr int get_arg_index_by_name(basic_string_view<Char> name,
|
||||
type_list<Args...>) {
|
||||
constexpr auto get_arg_index_by_name(basic_string_view<Char> name,
|
||||
type_list<Args...>) -> int {
|
||||
return get_arg_index_by_name<Args...>(name);
|
||||
}
|
||||
|
||||
@@ -105,8 +125,8 @@ template <typename Char> struct text {
|
||||
basic_string_view<Char> data;
|
||||
using char_type = Char;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
constexpr OutputIt format(OutputIt out, const Args&...) const {
|
||||
template <typename OutputIt, typename... T>
|
||||
constexpr auto format(OutputIt out, const T&...) const -> OutputIt {
|
||||
return write<Char>(out, data);
|
||||
}
|
||||
};
|
||||
@@ -115,8 +135,8 @@ template <typename Char>
|
||||
struct is_compiled_format<text<Char>> : std::true_type {};
|
||||
|
||||
template <typename Char>
|
||||
constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
|
||||
size_t size) {
|
||||
constexpr auto make_text(basic_string_view<Char> s, size_t pos, size_t size)
|
||||
-> text<Char> {
|
||||
return {{&s[pos], size}};
|
||||
}
|
||||
|
||||
@@ -124,8 +144,8 @@ template <typename Char> struct code_unit {
|
||||
Char value;
|
||||
using char_type = Char;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
constexpr OutputIt format(OutputIt out, const Args&...) const {
|
||||
template <typename OutputIt, typename... T>
|
||||
constexpr auto format(OutputIt out, const T&...) const -> OutputIt {
|
||||
*out++ = value;
|
||||
return out;
|
||||
}
|
||||
@@ -133,7 +153,7 @@ template <typename Char> struct code_unit {
|
||||
|
||||
// This ensures that the argument type is convertible to `const T&`.
|
||||
template <typename T, int N, typename... Args>
|
||||
constexpr const T& get_arg_checked(const Args&... args) {
|
||||
constexpr auto get_arg_checked(const Args&... args) -> const T& {
|
||||
const auto& arg = detail::get<N>(args...);
|
||||
if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) {
|
||||
return arg.value;
|
||||
@@ -146,13 +166,13 @@ template <typename Char>
|
||||
struct is_compiled_format<code_unit<Char>> : std::true_type {};
|
||||
|
||||
// A replacement field that refers to argument N.
|
||||
template <typename Char, typename T, int N> struct field {
|
||||
template <typename Char, typename V, int N> struct field {
|
||||
using char_type = Char;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
constexpr OutputIt format(OutputIt out, const Args&... args) const {
|
||||
const T& arg = get_arg_checked<T, N>(args...);
|
||||
if constexpr (std::is_convertible<T, basic_string_view<Char>>::value) {
|
||||
template <typename OutputIt, typename... T>
|
||||
constexpr auto format(OutputIt out, const T&... args) const -> OutputIt {
|
||||
const V& arg = get_arg_checked<V, N>(args...);
|
||||
if constexpr (std::is_convertible<V, basic_string_view<Char>>::value) {
|
||||
auto s = basic_string_view<Char>(arg);
|
||||
return copy<Char>(s.begin(), s.end(), out);
|
||||
} else {
|
||||
@@ -170,10 +190,10 @@ template <typename Char> struct runtime_named_field {
|
||||
basic_string_view<Char> name;
|
||||
|
||||
template <typename OutputIt, typename T>
|
||||
constexpr static bool try_format_argument(
|
||||
constexpr static auto try_format_argument(
|
||||
OutputIt& out,
|
||||
// [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9
|
||||
[[maybe_unused]] basic_string_view<Char> arg_name, const T& arg) {
|
||||
[[maybe_unused]] basic_string_view<Char> arg_name, const T& arg) -> bool {
|
||||
if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) {
|
||||
if (arg_name == arg.name) {
|
||||
out = write<Char>(out, arg.value);
|
||||
@@ -183,8 +203,8 @@ template <typename Char> struct runtime_named_field {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
constexpr OutputIt format(OutputIt out, const Args&... args) const {
|
||||
template <typename OutputIt, typename... T>
|
||||
constexpr auto format(OutputIt out, const T&... args) const -> OutputIt {
|
||||
bool found = (try_format_argument(out, name, args) || ...);
|
||||
if (!found) {
|
||||
FMT_THROW(format_error("argument with specified name is not found"));
|
||||
@@ -197,17 +217,17 @@ template <typename Char>
|
||||
struct is_compiled_format<runtime_named_field<Char>> : std::true_type {};
|
||||
|
||||
// A replacement field that refers to argument N and has format specifiers.
|
||||
template <typename Char, typename T, int N> struct spec_field {
|
||||
template <typename Char, typename V, int N> struct spec_field {
|
||||
using char_type = Char;
|
||||
formatter<T, Char> fmt;
|
||||
formatter<V, Char> fmt;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
constexpr FMT_INLINE OutputIt format(OutputIt out,
|
||||
const Args&... args) const {
|
||||
template <typename OutputIt, typename... T>
|
||||
constexpr FMT_INLINE auto format(OutputIt out, const T&... args) const
|
||||
-> OutputIt {
|
||||
const auto& vargs =
|
||||
fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...);
|
||||
basic_format_context<OutputIt, Char> ctx(out, vargs);
|
||||
return fmt.format(get_arg_checked<T, N>(args...), ctx);
|
||||
return fmt.format(get_arg_checked<V, N>(args...), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -219,8 +239,8 @@ template <typename L, typename R> struct concat {
|
||||
R rhs;
|
||||
using char_type = typename L::char_type;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
constexpr OutputIt format(OutputIt out, const Args&... args) const {
|
||||
template <typename OutputIt, typename... T>
|
||||
constexpr auto format(OutputIt out, const T&... args) const -> OutputIt {
|
||||
out = lhs.format(out, args...);
|
||||
return rhs.format(out, args...);
|
||||
}
|
||||
@@ -230,14 +250,14 @@ template <typename L, typename R>
|
||||
struct is_compiled_format<concat<L, R>> : std::true_type {};
|
||||
|
||||
template <typename L, typename R>
|
||||
constexpr concat<L, R> make_concat(L lhs, R rhs) {
|
||||
constexpr auto make_concat(L lhs, R rhs) -> concat<L, R> {
|
||||
return {lhs, rhs};
|
||||
}
|
||||
|
||||
struct unknown_format {};
|
||||
|
||||
template <typename Char>
|
||||
constexpr size_t parse_text(basic_string_view<Char> str, size_t pos) {
|
||||
constexpr auto parse_text(basic_string_view<Char> str, size_t pos) -> size_t {
|
||||
for (size_t size = str.size(); pos != size; ++pos) {
|
||||
if (str[pos] == '{' || str[pos] == '}') break;
|
||||
}
|
||||
@@ -270,8 +290,8 @@ template <typename T, typename Char> struct parse_specs_result {
|
||||
enum { manual_indexing_id = -1 };
|
||||
|
||||
template <typename T, typename Char>
|
||||
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
||||
size_t pos, int next_arg_id) {
|
||||
constexpr auto parse_specs(basic_string_view<Char> str, size_t pos,
|
||||
int next_arg_id) -> parse_specs_result<T, Char> {
|
||||
str.remove_prefix(pos);
|
||||
auto ctx =
|
||||
compile_parse_context<Char>(str, max_value<int>(), nullptr, next_arg_id);
|
||||
@@ -285,16 +305,16 @@ template <typename Char> struct arg_id_handler {
|
||||
arg_id_kind kind;
|
||||
arg_ref<Char> arg_id;
|
||||
|
||||
constexpr int on_auto() {
|
||||
constexpr auto on_auto() -> int {
|
||||
FMT_ASSERT(false, "handler cannot be used with automatic indexing");
|
||||
return 0;
|
||||
}
|
||||
constexpr int on_index(int id) {
|
||||
constexpr auto on_index(int id) -> int {
|
||||
kind = arg_id_kind::index;
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
}
|
||||
constexpr int on_name(basic_string_view<Char> id) {
|
||||
constexpr auto on_name(basic_string_view<Char> id) -> int {
|
||||
kind = arg_id_kind::name;
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
@@ -433,27 +453,28 @@ FMT_BEGIN_EXPORT
|
||||
|
||||
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
|
||||
|
||||
template <typename CompiledFormat, typename... Args,
|
||||
template <typename CompiledFormat, typename... T,
|
||||
typename Char = typename CompiledFormat::char_type,
|
||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
FMT_INLINE FMT_CONSTEXPR_STRING auto format(const CompiledFormat& cf,
|
||||
const T&... args)
|
||||
-> std::basic_string<Char> {
|
||||
auto s = std::basic_string<Char>();
|
||||
cf.format(std::back_inserter(s), args...);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||
template <typename OutputIt, typename CompiledFormat, typename... T,
|
||||
FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
|
||||
constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
constexpr FMT_INLINE auto format_to(OutputIt out, const CompiledFormat& cf,
|
||||
const T&... args) -> OutputIt {
|
||||
return cf.format(out, args...);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
template <typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||
Args&&... args) {
|
||||
FMT_INLINE FMT_CONSTEXPR_STRING auto format(const S&, T&&... args)
|
||||
-> std::basic_string<typename S::char_type> {
|
||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
||||
constexpr auto str = basic_string_view<typename S::char_type>(S());
|
||||
if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') {
|
||||
@@ -466,72 +487,97 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||
}
|
||||
}
|
||||
}
|
||||
constexpr auto compiled = detail::compile<Args...>(S());
|
||||
constexpr auto compiled = detail::compile<T...>(S());
|
||||
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||
detail::unknown_format>()) {
|
||||
return fmt::format(
|
||||
static_cast<basic_string_view<typename S::char_type>>(S()),
|
||||
std::forward<Args>(args)...);
|
||||
std::forward<T>(args)...);
|
||||
} else {
|
||||
return fmt::format(compiled, std::forward<Args>(args)...);
|
||||
return fmt::format(compiled, std::forward<T>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
template <typename OutputIt, typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
|
||||
constexpr auto compiled = detail::compile<Args...>(S());
|
||||
FMT_CONSTEXPR auto format_to(OutputIt out, const S&, T&&... args) -> OutputIt {
|
||||
constexpr auto compiled = detail::compile<T...>(S());
|
||||
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||
detail::unknown_format>()) {
|
||||
return fmt::format_to(
|
||||
out, static_cast<basic_string_view<typename S::char_type>>(S()),
|
||||
std::forward<Args>(args)...);
|
||||
std::forward<T>(args)...);
|
||||
} else {
|
||||
return fmt::format_to(out, compiled, std::forward<Args>(args)...);
|
||||
return fmt::format_to(out, compiled, std::forward<T>(args)...);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
template <typename OutputIt, typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args)
|
||||
auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
using traits = detail::fixed_buffer_traits;
|
||||
auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
|
||||
fmt::format_to(std::back_inserter(buf), fmt, std::forward<Args>(args)...);
|
||||
fmt::format_to(std::back_inserter(buf), fmt, std::forward<T>(args)...);
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
template <typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args)
|
||||
-> size_t {
|
||||
FMT_CONSTEXPR20 auto formatted_size(const S& fmt, T&&... args) -> size_t {
|
||||
auto buf = detail::counting_buffer<>();
|
||||
fmt::format_to(appender(buf), fmt, args...);
|
||||
fmt::format_to(appender(buf), fmt, std::forward<T>(args)...);
|
||||
return buf.count();
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
template <typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
void print(std::FILE* f, const S& fmt, const Args&... args) {
|
||||
void print(std::FILE* f, const S& fmt, T&&... args) {
|
||||
auto buf = memory_buffer();
|
||||
fmt::format_to(appender(buf), fmt, args...);
|
||||
fmt::format_to(appender(buf), fmt, std::forward<T>(args)...);
|
||||
detail::print(f, {buf.data(), buf.size()});
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
template <typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
void print(const S& fmt, const Args&... args) {
|
||||
print(stdout, fmt, args...);
|
||||
void print(const S& fmt, T&&... args) {
|
||||
print(stdout, fmt, std::forward<T>(args)...);
|
||||
}
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
inline namespace literals {
|
||||
template <detail::fixed_string Str> constexpr auto operator""_cf() {
|
||||
return FMT_COMPILE(Str.data);
|
||||
}
|
||||
} // namespace literals
|
||||
#endif
|
||||
template <size_t N> class static_format_result {
|
||||
private:
|
||||
char data[N];
|
||||
|
||||
public:
|
||||
template <typename S, typename... T,
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
explicit FMT_CONSTEXPR static_format_result(const S& fmt, T&&... args) {
|
||||
*fmt::format_to(data, fmt, std::forward<T>(args)...) = '\0';
|
||||
}
|
||||
|
||||
auto str() const -> fmt::string_view { return {data, N - 1}; }
|
||||
auto c_str() const -> const char* { return data; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats arguments according to the format string `fmt_str` and produces
|
||||
* a string of the exact required size at compile time. Both the format string
|
||||
* and the arguments must be compile-time expressions.
|
||||
*
|
||||
* The resulting string can be accessed as a C string via `c_str()` or as
|
||||
* a `fmt::string_view` via `str()`.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* // Produces the static string "42" at compile time.
|
||||
* static constexpr auto result = FMT_STATIC_FORMAT("{}", 42);
|
||||
* const char* s = result.c_str();
|
||||
*/
|
||||
#define FMT_STATIC_FORMAT(fmt_str, ...) \
|
||||
fmt::static_format_result< \
|
||||
fmt::formatted_size(FMT_COMPILE(fmt_str), __VA_ARGS__) + 1>( \
|
||||
FMT_COMPILE(fmt_str), __VA_ARGS__)
|
||||
|
||||
FMT_END_EXPORT
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
125
3rdparty/fmt/include/fmt/format-inl.h
vendored
125
3rdparty/fmt/include/fmt/format-inl.h
vendored
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
#if FMT_USE_LOCALE && !defined(FMT_MODULE)
|
||||
# include <locale>
|
||||
#endif
|
||||
|
||||
@@ -31,14 +31,49 @@
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
#ifndef FMT_CUSTOM_ASSERT_FAIL
|
||||
FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
|
||||
// Use unchecked std::fprintf to avoid triggering another assertion when
|
||||
// writing to stderr fails.
|
||||
fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
namespace detail {
|
||||
using std::locale;
|
||||
using std::numpunct;
|
||||
using std::use_facet;
|
||||
} // namespace detail
|
||||
|
||||
template <typename Locale, enable_if_t<(sizeof(Locale::collate) != 0), int>>
|
||||
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
||||
static_assert(std::is_same<Locale, std::locale>::value, "");
|
||||
}
|
||||
#else
|
||||
namespace detail {
|
||||
struct locale {};
|
||||
template <typename Char> struct numpunct {
|
||||
auto grouping() const -> std::string { return "\03"; }
|
||||
auto thousands_sep() const -> Char { return ','; }
|
||||
auto decimal_point() const -> Char { return '.'; }
|
||||
};
|
||||
template <typename Facet> Facet use_facet(locale) { return {}; }
|
||||
} // namespace detail
|
||||
#endif // FMT_USE_LOCALE
|
||||
|
||||
template <typename Locale> auto locale_ref::get() const -> Locale {
|
||||
using namespace detail;
|
||||
static_assert(std::is_same<Locale, locale>::value, "");
|
||||
#if FMT_USE_LOCALE
|
||||
if (locale_) return *static_cast<const locale*>(locale_);
|
||||
#endif
|
||||
return locale();
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
|
||||
string_view message) noexcept {
|
||||
@@ -79,33 +114,6 @@ inline void fwrite_all(const void* ptr, size_t count, FILE* stream) {
|
||||
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||
}
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
using std::locale;
|
||||
using std::numpunct;
|
||||
using std::use_facet;
|
||||
|
||||
template <typename Locale>
|
||||
locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
|
||||
static_assert(std::is_same<Locale, locale>::value, "");
|
||||
}
|
||||
#else
|
||||
struct locale {};
|
||||
template <typename Char> struct numpunct {
|
||||
auto grouping() const -> std::string { return "\03"; }
|
||||
auto thousands_sep() const -> Char { return ','; }
|
||||
auto decimal_point() const -> Char { return '.'; }
|
||||
};
|
||||
template <typename Facet> Facet use_facet(locale) { return {}; }
|
||||
#endif // FMT_USE_LOCALE
|
||||
|
||||
template <typename Locale> auto locale_ref::get() const -> Locale {
|
||||
static_assert(std::is_same<Locale, locale>::value, "");
|
||||
#if FMT_USE_LOCALE
|
||||
if (locale_) return *static_cast<const locale*>(locale_);
|
||||
#endif
|
||||
return locale();
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
|
||||
auto&& facet = use_facet<numpunct<Char>>(loc.get<locale>());
|
||||
@@ -133,14 +141,13 @@ FMT_FUNC auto write_loc(appender out, loc_value value,
|
||||
} // namespace detail
|
||||
|
||||
FMT_FUNC void report_error(const char* message) {
|
||||
#if FMT_USE_EXCEPTIONS
|
||||
// Use FMT_THROW instead of throw to avoid bogus unreachable code warnings
|
||||
// from MSVC.
|
||||
FMT_THROW(format_error(message));
|
||||
#else
|
||||
fputs(message, stderr);
|
||||
abort();
|
||||
#if FMT_MSC_VERSION || defined(__NVCC__)
|
||||
// Silence unreachable code warnings in MSVC and NVCC because these
|
||||
// are nearly impossible to fix in a generic code.
|
||||
volatile bool b = true;
|
||||
if (!b) return;
|
||||
#endif
|
||||
FMT_THROW(format_error(message));
|
||||
}
|
||||
|
||||
template <typename Locale> typename Locale::id format_facet<Locale>::id;
|
||||
@@ -174,11 +181,11 @@ inline auto operator==(basic_fp<F> x, basic_fp<F> y) -> bool {
|
||||
}
|
||||
|
||||
// Compilers should be able to optimize this into the ror instruction.
|
||||
FMT_CONSTEXPR inline auto rotr(uint32_t n, uint32_t r) noexcept -> uint32_t {
|
||||
FMT_INLINE auto rotr(uint32_t n, uint32_t r) noexcept -> uint32_t {
|
||||
r &= 31;
|
||||
return (n >> r) | (n << (32 - r));
|
||||
}
|
||||
FMT_CONSTEXPR inline auto rotr(uint64_t n, uint32_t r) noexcept -> uint64_t {
|
||||
FMT_INLINE auto rotr(uint64_t n, uint32_t r) noexcept -> uint64_t {
|
||||
r &= 63;
|
||||
return (n >> r) | (n << (64 - r));
|
||||
}
|
||||
@@ -275,7 +282,7 @@ template <> struct cache_accessor<float> {
|
||||
static auto get_cached_power(int k) noexcept -> uint64_t {
|
||||
FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,
|
||||
"k is out of range");
|
||||
static constexpr const uint64_t pow10_significands[] = {
|
||||
static constexpr uint64_t pow10_significands[] = {
|
||||
0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f,
|
||||
0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb,
|
||||
0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28,
|
||||
@@ -370,7 +377,7 @@ template <> struct cache_accessor<double> {
|
||||
FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k,
|
||||
"k is out of range");
|
||||
|
||||
static constexpr const uint128_fallback pow10_significands[] = {
|
||||
static constexpr uint128_fallback pow10_significands[] = {
|
||||
#if FMT_USE_FULL_CACHE_DRAGONBOX
|
||||
{0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
|
||||
{0x9faacf3df73609b1, 0x77b191618c54e9ad},
|
||||
@@ -1037,7 +1044,7 @@ template <> struct cache_accessor<double> {
|
||||
#if FMT_USE_FULL_CACHE_DRAGONBOX
|
||||
return pow10_significands[k - float_info<double>::min_k];
|
||||
#else
|
||||
static constexpr const uint64_t powers_of_5_64[] = {
|
||||
static constexpr uint64_t powers_of_5_64[] = {
|
||||
0x0000000000000001, 0x0000000000000005, 0x0000000000000019,
|
||||
0x000000000000007d, 0x0000000000000271, 0x0000000000000c35,
|
||||
0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1,
|
||||
@@ -1149,8 +1156,8 @@ auto is_left_endpoint_integer_shorter_interval(int exponent) noexcept -> bool {
|
||||
exponent <= case_shorter_interval_left_endpoint_upper_threshold;
|
||||
}
|
||||
|
||||
// Remove trailing zeros from n and return the number of zeros removed (float)
|
||||
FMT_INLINE int remove_trailing_zeros(uint32_t& n, int s = 0) noexcept {
|
||||
// Remove trailing zeros from n and return the number of zeros removed (float).
|
||||
FMT_INLINE auto remove_trailing_zeros(uint32_t& n, int s = 0) noexcept -> int {
|
||||
FMT_ASSERT(n != 0, "");
|
||||
// Modular inverse of 5 (mod 2^32): (mod_inv_5 * 5) mod 2^32 = 1.
|
||||
constexpr uint32_t mod_inv_5 = 0xcccccccd;
|
||||
@@ -1170,22 +1177,19 @@ FMT_INLINE int remove_trailing_zeros(uint32_t& n, int s = 0) noexcept {
|
||||
return s;
|
||||
}
|
||||
|
||||
// Removes trailing zeros and returns the number of zeros removed (double)
|
||||
FMT_INLINE int remove_trailing_zeros(uint64_t& n) noexcept {
|
||||
// Removes trailing zeros and returns the number of zeros removed (double).
|
||||
FMT_INLINE auto remove_trailing_zeros(uint64_t& n) noexcept -> int {
|
||||
FMT_ASSERT(n != 0, "");
|
||||
|
||||
// This magic number is ceil(2^90 / 10^8).
|
||||
constexpr uint64_t magic_number = 12379400392853802749ull;
|
||||
auto nm = umul128(n, magic_number);
|
||||
|
||||
// Is n is divisible by 10^8?
|
||||
if ((nm.high() & ((1ull << (90 - 64)) - 1)) == 0 && nm.low() < magic_number) {
|
||||
constexpr uint32_t ten_pow_8 = 100000000u;
|
||||
if ((n % ten_pow_8) == 0) {
|
||||
// If yes, work with the quotient...
|
||||
auto n32 = static_cast<uint32_t>(nm.high() >> (90 - 64));
|
||||
auto n32 = static_cast<uint32_t>(n / ten_pow_8);
|
||||
// ... and use the 32 bit variant of the function
|
||||
int s = remove_trailing_zeros(n32, 8);
|
||||
int num_zeros = remove_trailing_zeros(n32, 8);
|
||||
n = n32;
|
||||
return s;
|
||||
return num_zeros;
|
||||
}
|
||||
|
||||
// If n is not divisible by 10^8, work with n itself.
|
||||
@@ -1210,7 +1214,7 @@ FMT_INLINE int remove_trailing_zeros(uint64_t& n) noexcept {
|
||||
|
||||
// The main algorithm for shorter interval case
|
||||
template <typename T>
|
||||
FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) noexcept {
|
||||
FMT_INLINE auto shorter_interval_case(int exponent) noexcept -> decimal_fp<T> {
|
||||
decimal_fp<T> ret_value;
|
||||
// Compute k and beta
|
||||
const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
|
||||
@@ -1454,8 +1458,8 @@ FMT_FUNC void vformat_to(buffer<char>& buf, string_view fmt, format_args args,
|
||||
auto out = appender(buf);
|
||||
if (fmt.size() == 2 && equal2(fmt.data(), "{}"))
|
||||
return args.get(0).visit(default_arg_formatter<char>{out});
|
||||
parse_format_string(
|
||||
fmt, format_handler<char>{parse_context<char>(fmt), {out, args, loc}});
|
||||
parse_format_string(fmt,
|
||||
format_handler<>{parse_context<>(fmt), {out, args, loc}});
|
||||
}
|
||||
|
||||
template <typename T> struct span {
|
||||
@@ -1546,10 +1550,11 @@ template <typename F> class glibc_file : public file_base<F> {
|
||||
|
||||
void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; }
|
||||
|
||||
bool needs_flush() const {
|
||||
auto needs_flush() const -> bool {
|
||||
if ((this->file_->_flags & line_buffered) == 0) return false;
|
||||
char* end = this->file_->_IO_write_end;
|
||||
return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end));
|
||||
auto size = max_of<ptrdiff_t>(this->file_->_IO_write_ptr - end, 0);
|
||||
return memchr(end, '\n', static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
void flush() { fflush_unlocked(this->file_); }
|
||||
@@ -1573,7 +1578,7 @@ template <typename F> class apple_file : public file_base<F> {
|
||||
void init_buffer() {
|
||||
if (this->file_->_p) return;
|
||||
// Force buffer initialization by placing and removing a char in a buffer.
|
||||
putc_unlocked(0, this->file_);
|
||||
if (!FMT_CLANG_ANALYZER) putc_unlocked(0, this->file_);
|
||||
--this->file_->_p;
|
||||
++this->file_->_w;
|
||||
}
|
||||
@@ -1594,7 +1599,7 @@ template <typename F> class apple_file : public file_base<F> {
|
||||
this->file_->_w -= size;
|
||||
}
|
||||
|
||||
bool needs_flush() const {
|
||||
auto needs_flush() const -> bool {
|
||||
if ((this->file_->_flags & line_buffered) == 0) return false;
|
||||
return memchr(this->file_->_p + this->file_->_w, '\n',
|
||||
to_unsigned(-this->file_->_w));
|
||||
|
||||
819
3rdparty/fmt/include/fmt/format.h
vendored
819
3rdparty/fmt/include/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
3
3rdparty/fmt/include/fmt/os.h
vendored
3
3rdparty/fmt/include/fmt/os.h
vendored
@@ -29,7 +29,8 @@
|
||||
# if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
|
||||
defined(__linux__)) && \
|
||||
(!defined(WINAPI_FAMILY) || \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) && \
|
||||
!defined(__wasm__)
|
||||
# include <fcntl.h> // for O_RDONLY
|
||||
# define FMT_USE_FCNTL 1
|
||||
# else
|
||||
|
||||
4
3rdparty/fmt/include/fmt/ostream.h
vendored
4
3rdparty/fmt/include/fmt/ostream.h
vendored
@@ -33,8 +33,8 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
// Generate a unique explicit instantion in every translation unit using a tag
|
||||
// type in an anonymous namespace.
|
||||
// Generate a unique explicit instantiation in every translation unit using a
|
||||
// tag type in an anonymous namespace.
|
||||
namespace {
|
||||
struct file_access_tag {};
|
||||
} // namespace
|
||||
|
||||
59
3rdparty/fmt/include/fmt/printf.h
vendored
59
3rdparty/fmt/include/fmt/printf.h
vendored
@@ -9,7 +9,7 @@
|
||||
#define FMT_PRINTF_H_
|
||||
|
||||
#ifndef FMT_MODULE
|
||||
# include <algorithm> // std::max
|
||||
# include <algorithm> // std::find
|
||||
# include <limits> // std::numeric_limits
|
||||
#endif
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
template <typename T> struct printf_formatter {
|
||||
printf_formatter() = delete;
|
||||
};
|
||||
|
||||
template <typename Char> class basic_printf_context {
|
||||
private:
|
||||
basic_appender<Char> out_;
|
||||
@@ -33,8 +29,6 @@ template <typename Char> class basic_printf_context {
|
||||
|
||||
public:
|
||||
using char_type = Char;
|
||||
using parse_context_type = parse_context<Char>;
|
||||
template <typename T> using formatter_type = printf_formatter<T>;
|
||||
enum { builtin_types = 1 };
|
||||
|
||||
/// Constructs a `printf_context` object. References to the arguments are
|
||||
@@ -46,7 +40,7 @@ template <typename Char> class basic_printf_context {
|
||||
auto out() -> basic_appender<Char> { return out_; }
|
||||
void advance_to(basic_appender<Char>) {}
|
||||
|
||||
auto locale() -> detail::locale_ref { return {}; }
|
||||
auto locale() -> locale_ref { return {}; }
|
||||
|
||||
auto arg(int id) const -> basic_format_arg<basic_printf_context> {
|
||||
return args_.get(id);
|
||||
@@ -74,10 +68,9 @@ inline auto find<false, char>(const char* first, const char* last, char value,
|
||||
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
template <bool IsSigned> struct int_checker {
|
||||
template <bool IS_SIGNED> struct int_checker {
|
||||
template <typename T> static auto fits_in_int(T value) -> bool {
|
||||
unsigned max = to_unsigned(max_value<int>());
|
||||
return value <= max;
|
||||
return value <= to_unsigned(max_value<int>());
|
||||
}
|
||||
inline static auto fits_in_int(bool) -> bool { return true; }
|
||||
};
|
||||
@@ -95,7 +88,7 @@ struct printf_precision_handler {
|
||||
auto operator()(T value) -> int {
|
||||
if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
|
||||
report_error("number is too big");
|
||||
return (std::max)(static_cast<int>(value), 0);
|
||||
return max_of(static_cast<int>(value), 0);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
@@ -410,7 +403,9 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
arg_index = parse_ctx.next_arg_id();
|
||||
else
|
||||
parse_ctx.check_arg_id(--arg_index);
|
||||
return detail::get_arg(context, arg_index);
|
||||
auto arg = context.arg(arg_index);
|
||||
if (!arg) report_error("argument not found");
|
||||
return arg;
|
||||
};
|
||||
|
||||
const Char* start = parse_ctx.begin();
|
||||
@@ -571,15 +566,19 @@ inline auto vsprintf(basic_string_view<Char> fmt,
|
||||
*
|
||||
* std::string message = fmt::sprintf("The answer is %d", 42);
|
||||
*/
|
||||
template <typename S, typename... T, typename Char = detail::char_t<S>>
|
||||
inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
|
||||
return vsprintf(detail::to_string_view(fmt),
|
||||
fmt::make_format_args<basic_printf_context<Char>>(args...));
|
||||
template <typename... T>
|
||||
inline auto sprintf(string_view fmt, const T&... args) -> std::string {
|
||||
return vsprintf(fmt, make_printf_args(args...));
|
||||
}
|
||||
template <typename... T>
|
||||
FMT_DEPRECATED auto sprintf(basic_string_view<wchar_t> fmt, const T&... args)
|
||||
-> std::wstring {
|
||||
return vsprintf(fmt, make_printf_args<wchar_t>(args...));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline auto vfprintf(std::FILE* f, basic_string_view<Char> fmt,
|
||||
typename vprintf_args<Char>::type args) -> int {
|
||||
auto vfprintf(std::FILE* f, basic_string_view<Char> fmt,
|
||||
typename vprintf_args<Char>::type args) -> int {
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vprintf(buf, fmt, args);
|
||||
size_t size = buf.size();
|
||||
@@ -596,17 +595,14 @@ inline auto vfprintf(std::FILE* f, basic_string_view<Char> fmt,
|
||||
*
|
||||
* fmt::fprintf(stderr, "Don't %s!", "panic");
|
||||
*/
|
||||
template <typename S, typename... T, typename Char = detail::char_t<S>>
|
||||
inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
|
||||
return vfprintf(f, detail::to_string_view(fmt),
|
||||
make_printf_args<Char>(args...));
|
||||
template <typename... T>
|
||||
inline auto fprintf(std::FILE* f, string_view fmt, const T&... args) -> int {
|
||||
return vfprintf(f, fmt, make_printf_args(args...));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_DEPRECATED inline auto vprintf(basic_string_view<Char> fmt,
|
||||
typename vprintf_args<Char>::type args)
|
||||
-> int {
|
||||
return vfprintf(stdout, fmt, args);
|
||||
template <typename... T>
|
||||
FMT_DEPRECATED auto fprintf(std::FILE* f, basic_string_view<wchar_t> fmt,
|
||||
const T&... args) -> int {
|
||||
return vfprintf(f, fmt, make_printf_args<wchar_t>(args...));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,11 +617,6 @@ template <typename... T>
|
||||
inline auto printf(string_view fmt, const T&... args) -> int {
|
||||
return vfprintf(stdout, fmt, make_printf_args(args...));
|
||||
}
|
||||
template <typename... T>
|
||||
FMT_DEPRECATED inline auto printf(basic_string_view<wchar_t> fmt,
|
||||
const T&... args) -> int {
|
||||
return vfprintf(stdout, fmt, make_printf_args<wchar_t>(args...));
|
||||
}
|
||||
|
||||
FMT_END_EXPORT
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
48
3rdparty/fmt/include/fmt/ranges.h
vendored
48
3rdparty/fmt/include/fmt/ranges.h
vendored
@@ -11,7 +11,6 @@
|
||||
#ifndef FMT_MODULE
|
||||
# include <initializer_list>
|
||||
# include <iterator>
|
||||
# include <string>
|
||||
# include <tuple>
|
||||
# include <type_traits>
|
||||
# include <utility>
|
||||
@@ -31,7 +30,7 @@ template <typename T> class is_map {
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
@@ -40,17 +39,16 @@ template <typename T> class is_set {
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
|
||||
};
|
||||
|
||||
// C array overload
|
||||
template <typename T, std::size_t N>
|
||||
template <typename T, size_t N>
|
||||
auto range_begin(const T (&arr)[N]) -> const T* {
|
||||
return arr;
|
||||
}
|
||||
template <typename T, std::size_t N>
|
||||
auto range_end(const T (&arr)[N]) -> const T* {
|
||||
template <typename T, size_t N> auto range_end(const T (&arr)[N]) -> const T* {
|
||||
return arr + N;
|
||||
}
|
||||
|
||||
@@ -120,7 +118,7 @@ template <typename T> class is_tuple_like_ {
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
@@ -154,7 +152,7 @@ using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
|
||||
template <typename T, typename C, bool = is_tuple_like_<T>::value>
|
||||
class is_tuple_formattable_ {
|
||||
public:
|
||||
static constexpr const bool value = false;
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
|
||||
template <size_t... Is>
|
||||
@@ -170,7 +168,7 @@ template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
|
||||
C>::value)...>{}));
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
decltype(check(tuple_index_sequence<T>{}))::value;
|
||||
};
|
||||
|
||||
@@ -208,7 +206,7 @@ template <typename Char, typename... T>
|
||||
using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
|
||||
|
||||
using std::get;
|
||||
template <typename Tuple, typename Char, std::size_t... Is>
|
||||
template <typename Tuple, typename Char, size_t... Is>
|
||||
auto get_formatters(index_sequence<Is...>)
|
||||
-> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
|
||||
} // namespace tuple
|
||||
@@ -219,7 +217,7 @@ template <typename R> struct range_reference_type_impl {
|
||||
using type = decltype(*detail::range_begin(std::declval<R&>()));
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
|
||||
template <typename T, size_t N> struct range_reference_type_impl<T[N]> {
|
||||
using type = T&;
|
||||
};
|
||||
|
||||
@@ -281,14 +279,15 @@ template <typename FormatContext> struct format_tuple_element {
|
||||
|
||||
} // namespace detail
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename T> struct is_tuple_like {
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
|
||||
};
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename T, typename C> struct is_tuple_formattable {
|
||||
static constexpr const bool value =
|
||||
detail::is_tuple_formattable_<T, C>::value;
|
||||
static constexpr bool value = detail::is_tuple_formattable_<T, C>::value;
|
||||
};
|
||||
|
||||
template <typename Tuple, typename Char>
|
||||
@@ -343,8 +342,9 @@ struct formatter<Tuple, Char,
|
||||
}
|
||||
};
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename T, typename Char> struct is_range {
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
detail::is_range_<T>::value && !detail::has_to_string_view<T>::value;
|
||||
};
|
||||
|
||||
@@ -368,6 +368,7 @@ template <typename P1, typename... Pn>
|
||||
struct conjunction<P1, Pn...>
|
||||
: conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename T, typename Char, typename Enable = void>
|
||||
struct range_formatter;
|
||||
|
||||
@@ -670,7 +671,8 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Tuple> struct tuple_join_view : detail::view {
|
||||
FMT_EXPORT
|
||||
template <typename Tuple, typename Char> struct tuple_join_view : detail::view {
|
||||
const Tuple& tuple;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
@@ -685,15 +687,15 @@ template <typename Char, typename Tuple> struct tuple_join_view : detail::view {
|
||||
# define FMT_TUPLE_JOIN_SPECIFIERS 0
|
||||
#endif
|
||||
|
||||
template <typename Char, typename Tuple>
|
||||
struct formatter<tuple_join_view<Char, Tuple>, Char,
|
||||
template <typename Tuple, typename Char>
|
||||
struct formatter<tuple_join_view<Tuple, Char>, Char,
|
||||
enable_if_t<is_tuple_like<Tuple>::value>> {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return do_parse(ctx, std::tuple_size<Tuple>());
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const tuple_join_view<Char, Tuple>& value,
|
||||
auto format(const tuple_join_view<Tuple, Char>& value,
|
||||
FormatContext& ctx) const -> typename FormatContext::iterator {
|
||||
return do_format(value, ctx, std::tuple_size<Tuple>());
|
||||
}
|
||||
@@ -725,14 +727,14 @@ struct formatter<tuple_join_view<Char, Tuple>, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto do_format(const tuple_join_view<Char, Tuple>&, FormatContext& ctx,
|
||||
auto do_format(const tuple_join_view<Tuple, Char>&, FormatContext& ctx,
|
||||
std::integral_constant<size_t, 0>) const ->
|
||||
typename FormatContext::iterator {
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
template <typename FormatContext, size_t N>
|
||||
auto do_format(const tuple_join_view<Char, Tuple>& value, FormatContext& ctx,
|
||||
auto do_format(const tuple_join_view<Tuple, Char>& value, FormatContext& ctx,
|
||||
std::integral_constant<size_t, N>) const ->
|
||||
typename FormatContext::iterator {
|
||||
using std::get;
|
||||
@@ -754,7 +756,7 @@ template <typename T> class is_container_adaptor_like {
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
static constexpr bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
@@ -825,7 +827,7 @@ auto join(Range&& r, string_view sep)
|
||||
*/
|
||||
template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
|
||||
FMT_CONSTEXPR auto join(const Tuple& tuple, string_view sep)
|
||||
-> tuple_join_view<char, Tuple> {
|
||||
-> tuple_join_view<Tuple, char> {
|
||||
return {tuple, sep};
|
||||
}
|
||||
|
||||
|
||||
425
3rdparty/fmt/include/fmt/std.h
vendored
425
3rdparty/fmt/include/fmt/std.h
vendored
@@ -15,15 +15,13 @@
|
||||
# include <atomic>
|
||||
# include <bitset>
|
||||
# include <complex>
|
||||
# include <cstdlib>
|
||||
# include <exception>
|
||||
# include <functional>
|
||||
# include <functional> // std::reference_wrapper
|
||||
# include <memory>
|
||||
# include <thread>
|
||||
# include <type_traits>
|
||||
# include <typeinfo>
|
||||
# include <utility>
|
||||
# include <vector>
|
||||
# include <typeinfo> // std::type_info
|
||||
# include <utility> // std::make_index_sequence
|
||||
|
||||
// Check FMT_CPLUSPLUS to suppress a bogus warning in MSVC.
|
||||
# if FMT_CPLUSPLUS >= 201703L
|
||||
@@ -62,27 +60,26 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// For older Xcode versions, __cpp_lib_xxx flags are inaccurately defined.
|
||||
#ifndef FMT_CPP_LIB_FILESYSTEM
|
||||
# ifdef __cpp_lib_filesystem
|
||||
# define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem
|
||||
# else
|
||||
# define FMT_CPP_LIB_FILESYSTEM 0
|
||||
# endif
|
||||
#ifdef FMT_CPP_LIB_FILESYSTEM
|
||||
// Use the provided definition.
|
||||
#elif defined(__cpp_lib_filesystem)
|
||||
# define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem
|
||||
#else
|
||||
# define FMT_CPP_LIB_FILESYSTEM 0
|
||||
#endif
|
||||
|
||||
#ifndef FMT_CPP_LIB_VARIANT
|
||||
# ifdef __cpp_lib_variant
|
||||
# define FMT_CPP_LIB_VARIANT __cpp_lib_variant
|
||||
# else
|
||||
# define FMT_CPP_LIB_VARIANT 0
|
||||
# endif
|
||||
#ifdef FMT_CPP_LIB_VARIANT
|
||||
// Use the provided definition.
|
||||
#elif defined(__cpp_lib_variant)
|
||||
# define FMT_CPP_LIB_VARIANT __cpp_lib_variant
|
||||
#else
|
||||
# define FMT_CPP_LIB_VARIANT 0
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
#if FMT_CPP_LIB_FILESYSTEM
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Char, typename PathChar>
|
||||
auto get_path_string(const std::filesystem::path& p,
|
||||
@@ -111,8 +108,168 @@ void write_escaped_path(basic_memory_buffer<Char>& quoted,
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FMT_CPP_LIB_FILESYSTEM
|
||||
|
||||
#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT
|
||||
template <typename Char, typename OutputIt, typename T>
|
||||
auto write_escaped_alternative(OutputIt out, const T& v) -> OutputIt {
|
||||
if constexpr (has_to_string_view<T>::value)
|
||||
return write_escaped_string<Char>(out, detail::to_string_view(v));
|
||||
if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v);
|
||||
return write<Char>(out, v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FMT_CPP_LIB_VARIANT
|
||||
|
||||
template <typename> struct is_variant_like_ : std::false_type {};
|
||||
template <typename... Types>
|
||||
struct is_variant_like_<std::variant<Types...>> : std::true_type {};
|
||||
|
||||
template <typename Variant, typename Char> class is_variant_formattable {
|
||||
template <size_t... Is>
|
||||
static auto check(std::index_sequence<Is...>) -> std::conjunction<
|
||||
is_formattable<std::variant_alternative_t<Is, Variant>, Char>...>;
|
||||
|
||||
public:
|
||||
static constexpr bool value = decltype(check(
|
||||
std::make_index_sequence<std::variant_size<Variant>::value>()))::value;
|
||||
};
|
||||
|
||||
#endif // FMT_CPP_LIB_VARIANT
|
||||
|
||||
#if FMT_USE_RTTI
|
||||
|
||||
template <typename OutputIt>
|
||||
auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
|
||||
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
|
||||
int status = 0;
|
||||
size_t size = 0;
|
||||
std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
|
||||
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
|
||||
|
||||
string_view demangled_name_view;
|
||||
if (demangled_name_ptr) {
|
||||
demangled_name_view = demangled_name_ptr.get();
|
||||
|
||||
// Normalization of stdlib inline namespace names.
|
||||
// libc++ inline namespaces.
|
||||
// std::__1::* -> std::*
|
||||
// std::__1::__fs::* -> std::*
|
||||
// libstdc++ inline namespaces.
|
||||
// std::__cxx11::* -> std::*
|
||||
// std::filesystem::__cxx11::* -> std::filesystem::*
|
||||
if (demangled_name_view.starts_with("std::")) {
|
||||
char* begin = demangled_name_ptr.get();
|
||||
char* to = begin + 5; // std::
|
||||
for (char *from = to, *end = begin + demangled_name_view.size();
|
||||
from < end;) {
|
||||
// This is safe, because demangled_name is NUL-terminated.
|
||||
if (from[0] == '_' && from[1] == '_') {
|
||||
char* next = from + 1;
|
||||
while (next < end && *next != ':') next++;
|
||||
if (next[0] == ':' && next[1] == ':') {
|
||||
from = next + 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*to++ = *from++;
|
||||
}
|
||||
demangled_name_view = {begin, detail::to_unsigned(to - begin)};
|
||||
}
|
||||
} else {
|
||||
demangled_name_view = string_view(ti.name());
|
||||
}
|
||||
return detail::write_bytes<char>(out, demangled_name_view);
|
||||
# elif FMT_MSC_VERSION
|
||||
const string_view demangled_name(ti.name());
|
||||
for (size_t i = 0; i < demangled_name.size(); ++i) {
|
||||
auto sub = demangled_name;
|
||||
sub.remove_prefix(i);
|
||||
if (sub.starts_with("enum ")) {
|
||||
i += 4;
|
||||
continue;
|
||||
}
|
||||
if (sub.starts_with("class ") || sub.starts_with("union ")) {
|
||||
i += 5;
|
||||
continue;
|
||||
}
|
||||
if (sub.starts_with("struct ")) {
|
||||
i += 6;
|
||||
continue;
|
||||
}
|
||||
if (*sub.begin() != ' ') *out++ = *sub.begin();
|
||||
}
|
||||
return out;
|
||||
# else
|
||||
return detail::write_bytes<char>(out, string_view(ti.name()));
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif // FMT_USE_RTTI
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_flip : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_flip<T, void_t<decltype(std::declval<T>().flip())>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename T> struct is_bit_reference_like {
|
||||
static constexpr bool value = std::is_convertible<T, bool>::value &&
|
||||
std::is_nothrow_assignable<T, bool>::value &&
|
||||
has_flip<T>::value;
|
||||
};
|
||||
|
||||
// Workaround for libc++ incompatibility with C++ standard.
|
||||
// According to the Standard, `bitset::operator[] const` returns bool.
|
||||
#if defined(_LIBCPP_VERSION) && !defined(FMT_IMPORT_STD)
|
||||
template <typename C>
|
||||
struct is_bit_reference_like<std::__bit_const_reference<C>> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_format_as : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_format_as<T, void_t<decltype(format_as(std::declval<const T&>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_format_as_member : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_format_as_member<
|
||||
T, void_t<decltype(formatter<T>::format_as(std::declval<const T&>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename Deleter>
|
||||
auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* {
|
||||
return p.get();
|
||||
}
|
||||
template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
|
||||
return p.get();
|
||||
}
|
||||
|
||||
#if FMT_CPP_LIB_FILESYSTEM
|
||||
|
||||
class path : public std::filesystem::path {
|
||||
public:
|
||||
auto display_string() const -> std::string {
|
||||
const std::filesystem::path& base = *this;
|
||||
return fmt::format(FMT_STRING("{}"), base);
|
||||
}
|
||||
auto system_string() const -> std::string { return string(); }
|
||||
|
||||
auto generic_display_string() const -> std::string {
|
||||
const std::filesystem::path& base = *this;
|
||||
return fmt::format(FMT_STRING("{:g}"), base);
|
||||
}
|
||||
auto generic_system_string() const -> std::string { return generic_string(); }
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<std::filesystem::path, Char> {
|
||||
private:
|
||||
format_specs specs_;
|
||||
@@ -162,39 +319,20 @@ template <typename Char> struct formatter<std::filesystem::path, Char> {
|
||||
}
|
||||
};
|
||||
|
||||
class path : public std::filesystem::path {
|
||||
public:
|
||||
auto display_string() const -> std::string {
|
||||
const std::filesystem::path& base = *this;
|
||||
return fmt::format(FMT_STRING("{}"), base);
|
||||
}
|
||||
auto system_string() const -> std::string { return string(); }
|
||||
|
||||
auto generic_display_string() const -> std::string {
|
||||
const std::filesystem::path& base = *this;
|
||||
return fmt::format(FMT_STRING("{:g}"), base);
|
||||
}
|
||||
auto generic_system_string() const -> std::string { return generic_string(); }
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
#endif // FMT_CPP_LIB_FILESYSTEM
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <std::size_t N, typename Char>
|
||||
template <size_t N, typename Char>
|
||||
struct formatter<std::bitset<N>, Char>
|
||||
: nested_formatter<basic_string_view<Char>, Char> {
|
||||
private:
|
||||
// Functor because C++11 doesn't support generic lambdas.
|
||||
// This is a functor because C++11 doesn't support generic lambdas.
|
||||
struct writer {
|
||||
const std::bitset<N>& bs;
|
||||
|
||||
template <typename OutputIt>
|
||||
FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt {
|
||||
for (auto pos = N; pos > 0; --pos) {
|
||||
for (auto pos = N; pos > 0; --pos)
|
||||
out = detail::write<Char>(out, bs[pos - 1] ? Char('1') : Char('0'));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
};
|
||||
@@ -209,10 +347,8 @@ struct formatter<std::bitset<N>, Char>
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#ifdef __cpp_lib_optional
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <typename T, typename Char>
|
||||
struct formatter<std::optional<T>, Char,
|
||||
std::enable_if_t<is_formattable<T, Char>::value>> {
|
||||
@@ -251,30 +387,9 @@ struct formatter<std::optional<T>, Char,
|
||||
return detail::write(out, ')');
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif // __cpp_lib_optional
|
||||
|
||||
#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
template <typename Char, typename OutputIt, typename T>
|
||||
auto write_escaped_alternative(OutputIt out, const T& v) -> OutputIt {
|
||||
if constexpr (has_to_string_view<T>::value)
|
||||
return write_escaped_string<Char>(out, detail::to_string_view(v));
|
||||
if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v);
|
||||
return write<Char>(out, v);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
#ifdef __cpp_lib_expected
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
template <typename T, typename E, typename Char>
|
||||
struct formatter<std::expected<T, E>, Char,
|
||||
std::enable_if_t<(std::is_void<T>::value ||
|
||||
@@ -301,11 +416,9 @@ struct formatter<std::expected<T, E>, Char,
|
||||
return out;
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif // __cpp_lib_expected
|
||||
|
||||
#ifdef __cpp_lib_source_location
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <> struct formatter<std::source_location> {
|
||||
FMT_CONSTEXPR auto parse(parse_context<>& ctx) { return ctx.begin(); }
|
||||
|
||||
@@ -323,42 +436,12 @@ template <> struct formatter<std::source_location> {
|
||||
return out;
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
#if FMT_CPP_LIB_VARIANT
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
using variant_index_sequence =
|
||||
std::make_index_sequence<std::variant_size<T>::value>;
|
||||
|
||||
template <typename> struct is_variant_like_ : std::false_type {};
|
||||
template <typename... Types>
|
||||
struct is_variant_like_<std::variant<Types...>> : std::true_type {};
|
||||
|
||||
// formattable element check.
|
||||
template <typename T, typename C> class is_variant_formattable_ {
|
||||
template <std::size_t... Is>
|
||||
static std::conjunction<
|
||||
is_formattable<std::variant_alternative_t<Is, T>, C>...>
|
||||
check(std::index_sequence<Is...>);
|
||||
|
||||
public:
|
||||
static constexpr const bool value =
|
||||
decltype(check(variant_index_sequence<T>{}))::value;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T> struct is_variant_like {
|
||||
static constexpr const bool value = detail::is_variant_like_<T>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename C> struct is_variant_formattable {
|
||||
static constexpr const bool value =
|
||||
detail::is_variant_formattable_<T, C>::value;
|
||||
static constexpr bool value = detail::is_variant_like_<T>::value;
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<std::monostate, Char> {
|
||||
@@ -374,10 +457,10 @@ template <typename Char> struct formatter<std::monostate, Char> {
|
||||
};
|
||||
|
||||
template <typename Variant, typename Char>
|
||||
struct formatter<
|
||||
Variant, Char,
|
||||
std::enable_if_t<std::conjunction_v<
|
||||
is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
|
||||
struct formatter<Variant, Char,
|
||||
std::enable_if_t<std::conjunction_v<
|
||||
is_variant_like<Variant>,
|
||||
detail::is_variant_formattable<Variant, Char>>>> {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
@@ -402,10 +485,9 @@ struct formatter<
|
||||
return out;
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_CPP_LIB_VARIANT
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <> struct formatter<std::error_code> {
|
||||
private:
|
||||
format_specs specs_;
|
||||
@@ -459,101 +541,29 @@ template <> struct formatter<std::error_code> {
|
||||
};
|
||||
|
||||
#if FMT_USE_RTTI
|
||||
namespace detail {
|
||||
|
||||
template <typename Char, typename OutputIt>
|
||||
auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt {
|
||||
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
|
||||
int status = 0;
|
||||
std::size_t size = 0;
|
||||
std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
|
||||
abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
|
||||
|
||||
string_view demangled_name_view;
|
||||
if (demangled_name_ptr) {
|
||||
demangled_name_view = demangled_name_ptr.get();
|
||||
|
||||
// Normalization of stdlib inline namespace names.
|
||||
// libc++ inline namespaces.
|
||||
// std::__1::* -> std::*
|
||||
// std::__1::__fs::* -> std::*
|
||||
// libstdc++ inline namespaces.
|
||||
// std::__cxx11::* -> std::*
|
||||
// std::filesystem::__cxx11::* -> std::filesystem::*
|
||||
if (demangled_name_view.starts_with("std::")) {
|
||||
char* begin = demangled_name_ptr.get();
|
||||
char* to = begin + 5; // std::
|
||||
for (char *from = to, *end = begin + demangled_name_view.size();
|
||||
from < end;) {
|
||||
// This is safe, because demangled_name is NUL-terminated.
|
||||
if (from[0] == '_' && from[1] == '_') {
|
||||
char* next = from + 1;
|
||||
while (next < end && *next != ':') next++;
|
||||
if (next[0] == ':' && next[1] == ':') {
|
||||
from = next + 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*to++ = *from++;
|
||||
}
|
||||
demangled_name_view = {begin, detail::to_unsigned(to - begin)};
|
||||
}
|
||||
} else {
|
||||
demangled_name_view = string_view(ti.name());
|
||||
}
|
||||
return detail::write_bytes<Char>(out, demangled_name_view);
|
||||
# elif FMT_MSC_VERSION
|
||||
const string_view demangled_name(ti.name());
|
||||
for (std::size_t i = 0; i < demangled_name.size(); ++i) {
|
||||
auto sub = demangled_name;
|
||||
sub.remove_prefix(i);
|
||||
if (sub.starts_with("enum ")) {
|
||||
i += 4;
|
||||
continue;
|
||||
}
|
||||
if (sub.starts_with("class ") || sub.starts_with("union ")) {
|
||||
i += 5;
|
||||
continue;
|
||||
}
|
||||
if (sub.starts_with("struct ")) {
|
||||
i += 6;
|
||||
continue;
|
||||
}
|
||||
if (*sub.begin() != ' ') *out++ = *sub.begin();
|
||||
}
|
||||
return out;
|
||||
# else
|
||||
return detail::write_bytes<Char>(out, string_view(ti.name()));
|
||||
# endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<std::type_info, Char // DEPRECATED! Mixing code unit types.
|
||||
> {
|
||||
template <> struct formatter<std::type_info> {
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename Context>
|
||||
auto format(const std::type_info& ti, Context& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return detail::write_demangled_name<Char>(ctx.out(), ti);
|
||||
return detail::write_demangled_name(ctx.out(), ti);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif // FMT_USE_RTTI
|
||||
|
||||
template <typename T, typename Char>
|
||||
template <typename T>
|
||||
struct formatter<
|
||||
T, Char, // DEPRECATED! Mixing code unit types.
|
||||
T, char,
|
||||
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
|
||||
private:
|
||||
bool with_typename_ = false;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* {
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
if (it == end || *it == '}') return it;
|
||||
@@ -570,43 +580,15 @@ struct formatter<
|
||||
auto out = ctx.out();
|
||||
#if FMT_USE_RTTI
|
||||
if (with_typename_) {
|
||||
out = detail::write_demangled_name<Char>(out, typeid(ex));
|
||||
out = detail::write_demangled_name(out, typeid(ex));
|
||||
*out++ = ':';
|
||||
*out++ = ' ';
|
||||
}
|
||||
#endif
|
||||
return detail::write_bytes<Char>(out, string_view(ex.what()));
|
||||
return detail::write_bytes<char>(out, string_view(ex.what()));
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct has_flip : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_flip<T, void_t<decltype(std::declval<T>().flip())>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename T> struct is_bit_reference_like {
|
||||
static constexpr const bool value =
|
||||
std::is_convertible<T, bool>::value &&
|
||||
std::is_nothrow_assignable<T, bool>::value && has_flip<T>::value;
|
||||
};
|
||||
|
||||
#ifdef _LIBCPP_VERSION
|
||||
|
||||
// Workaround for libc++ incompatibility with C++ standard.
|
||||
// According to the Standard, `bitset::operator[] const` returns bool.
|
||||
template <typename C>
|
||||
struct is_bit_reference_like<std::__bit_const_reference<C>> {
|
||||
static constexpr const bool value = true;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// We can't use std::vector<bool, Allocator>::reference and
|
||||
// std::bitset<N>::reference because the compiler can't deduce Allocator and N
|
||||
// in partial specialization.
|
||||
@@ -621,14 +603,6 @@ struct formatter<BitRef, Char,
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Deleter>
|
||||
auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* {
|
||||
return p.get();
|
||||
}
|
||||
template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
|
||||
return p.get();
|
||||
}
|
||||
|
||||
template <typename T, typename Char>
|
||||
struct formatter<std::atomic<T>, Char,
|
||||
enable_if_t<is_formattable<T, Char>::value>>
|
||||
@@ -715,7 +689,11 @@ template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
||||
|
||||
template <typename T, typename Char>
|
||||
struct formatter<std::reference_wrapper<T>, Char,
|
||||
enable_if_t<is_formattable<remove_cvref_t<T>, Char>::value>>
|
||||
// Guard against format_as because reference_wrapper is
|
||||
// implicitly convertible to T&.
|
||||
enable_if_t<is_formattable<remove_cvref_t<T>, Char>::value &&
|
||||
!detail::has_format_as<T>::value &&
|
||||
!detail::has_format_as_member<T>::value>>
|
||||
: formatter<remove_cvref_t<T>, Char> {
|
||||
template <typename FormatContext>
|
||||
auto format(std::reference_wrapper<T> ref, FormatContext& ctx) const
|
||||
@@ -725,4 +703,5 @@ struct formatter<std::reference_wrapper<T>, Char,
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_STD_H_
|
||||
|
||||
73
3rdparty/fmt/include/fmt/xchar.h
vendored
73
3rdparty/fmt/include/fmt/xchar.h
vendored
@@ -55,6 +55,16 @@ inline auto write_loc(basic_appender<wchar_t> out, loc_value value,
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
|
||||
basic_format_args<buffered_context<Char>> args,
|
||||
locale_ref loc = {}) {
|
||||
static_assert(!std::is_same<Char, char>::value, "");
|
||||
auto out = basic_appender<Char>(buf);
|
||||
parse_format_string(
|
||||
fmt, format_handler<Char>{parse_context<Char>(fmt), {out, args, loc}});
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
FMT_BEGIN_EXPORT
|
||||
@@ -112,10 +122,6 @@ inline auto runtime(wstring_view s) -> runtime_format_string<wchar_t> {
|
||||
return {{s}};
|
||||
}
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
template <> struct is_char<char8_t> : bool_constant<detail::is_utf8_enabled> {};
|
||||
#endif
|
||||
|
||||
template <typename... T>
|
||||
constexpr auto make_wformat_args(T&... args)
|
||||
-> decltype(fmt::make_format_args<wformat_context>(args...)) {
|
||||
@@ -151,13 +157,13 @@ auto join(std::initializer_list<T> list, wstring_view sep)
|
||||
|
||||
template <typename Tuple, FMT_ENABLE_IF(is_tuple_like<Tuple>::value)>
|
||||
auto join(const Tuple& tuple, basic_string_view<wchar_t> sep)
|
||||
-> tuple_join_view<wchar_t, Tuple> {
|
||||
-> tuple_join_view<Tuple, wchar_t> {
|
||||
return {tuple, sep};
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
auto vformat(basic_string_view<Char> fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
basic_format_args<buffered_context<Char>> args)
|
||||
-> std::basic_string<Char> {
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buf, fmt, args);
|
||||
@@ -187,24 +193,20 @@ auto format(const S& fmt, T&&... args) -> std::basic_string<Char> {
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
template <typename Locale, typename S,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat(const Locale& loc, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
template <typename S, typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat(locale_ref loc, const S& fmt,
|
||||
basic_format_args<buffered_context<Char>> args)
|
||||
-> std::basic_string<Char> {
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt), args,
|
||||
detail::locale_ref(loc));
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt), args, loc);
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename... T,
|
||||
template <typename S, typename... T,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto format(const Locale& loc, const S& fmt, T&&... args)
|
||||
FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
|
||||
inline auto format(locale_ref loc, const S& fmt, T&&... args)
|
||||
-> std::basic_string<Char> {
|
||||
return vformat(loc, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
@@ -215,7 +217,7 @@ template <typename OutputIt, typename S,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
auto vformat_to(OutputIt out, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args) -> OutputIt {
|
||||
basic_format_args<buffered_context<Char>> args) -> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt), args);
|
||||
return detail::get_iterator(buf, out);
|
||||
@@ -231,27 +233,24 @@ inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt {
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
template <typename Locale, typename S, typename OutputIt, typename... Args,
|
||||
template <typename S, typename OutputIt, typename... Args,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_locale<Locale>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to(OutputIt out, const Locale& loc, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to(OutputIt out, locale_ref loc, const S& fmt,
|
||||
basic_format_args<buffered_context<Char>> args)
|
||||
-> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
vformat_to(buf, detail::to_string_view(fmt), args, detail::locale_ref(loc));
|
||||
vformat_to(buf, detail::to_string_view(fmt), args, loc);
|
||||
return detail::get_iterator(buf, out);
|
||||
}
|
||||
|
||||
template <typename Locale, typename OutputIt, typename S, typename... T,
|
||||
template <typename OutputIt, typename S, typename... T,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
bool enable = detail::is_output_iterator<OutputIt, Char>::value &&
|
||||
detail::is_locale<Locale>::value &&
|
||||
detail::is_exotic_char<Char>::value>
|
||||
inline auto format_to(OutputIt out, const Locale& loc, const S& fmt,
|
||||
T&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
inline auto format_to(OutputIt out, locale_ref loc, const S& fmt, T&&... args)
|
||||
-> typename std::enable_if<enable, OutputIt>::type {
|
||||
return vformat_to(out, loc, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
@@ -260,7 +259,7 @@ template <typename OutputIt, typename Char, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
inline auto vformat_to_n(OutputIt out, size_t n, basic_string_view<Char> fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
basic_format_args<buffered_context<Char>> args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
using traits = detail::fixed_buffer_traits;
|
||||
auto buf = detail::iterator_buffer<OutputIt, Char, traits>(out, n);
|
||||
@@ -331,18 +330,6 @@ inline auto format(text_style ts, wformat_string<T...> fmt, T&&... args)
|
||||
return fmt::vformat(ts, fmt, fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
FMT_DEPRECATED void print(std::FILE* f, text_style ts, wformat_string<T...> fmt,
|
||||
const T&... args) {
|
||||
vprint(f, ts, fmt, fmt::make_wformat_args(args...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
FMT_DEPRECATED void print(text_style ts, wformat_string<T...> fmt,
|
||||
const T&... args) {
|
||||
return print(stdout, ts, fmt, args...);
|
||||
}
|
||||
|
||||
inline void vprint(std::wostream& os, wstring_view fmt, wformat_args args) {
|
||||
auto buffer = basic_memory_buffer<wchar_t>();
|
||||
detail::vformat_to(buffer, fmt, args);
|
||||
|
||||
2
3rdparty/fmt/src/fmt.cc
vendored
2
3rdparty/fmt/src/fmt.cc
vendored
@@ -50,6 +50,8 @@ module;
|
||||
# include <limits.h>
|
||||
# include <stdint.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <time.h>
|
||||
#endif
|
||||
#include <cerrno>
|
||||
|
||||
17
3rdparty/fmt/src/format.cc
vendored
17
3rdparty/fmt/src/format.cc
vendored
@@ -8,6 +8,12 @@
|
||||
#include "fmt/format-inl.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
template FMT_API locale_ref::locale_ref(const std::locale& loc);
|
||||
template FMT_API auto locale_ref::get<std::locale>() const -> std::locale;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template FMT_API auto dragonbox::to_decimal(float x) noexcept
|
||||
@@ -15,12 +21,6 @@ template FMT_API auto dragonbox::to_decimal(float x) noexcept
|
||||
template FMT_API auto dragonbox::to_decimal(double x) noexcept
|
||||
-> dragonbox::decimal_fp<double>;
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
// DEPRECATED! locale_ref in the detail namespace
|
||||
template FMT_API locale_ref::locale_ref(const std::locale& loc);
|
||||
template FMT_API auto locale_ref::get<std::locale>() const -> std::locale;
|
||||
#endif
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template FMT_API auto thousands_sep_impl(locale_ref)
|
||||
@@ -30,16 +30,13 @@ template FMT_API auto decimal_point_impl(locale_ref) -> char;
|
||||
// DEPRECATED!
|
||||
template FMT_API void buffer<char>::append(const char*, const char*);
|
||||
|
||||
// DEPRECATED!
|
||||
template FMT_API void vformat_to(buffer<char>&, string_view,
|
||||
typename vformat_args<>::type, locale_ref);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template FMT_API auto thousands_sep_impl(locale_ref)
|
||||
-> thousands_sep_result<wchar_t>;
|
||||
template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
|
||||
|
||||
// DEPRECATED!
|
||||
template FMT_API void buffer<wchar_t>::append(const wchar_t*, const wchar_t*);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
20
3rdparty/fmt/src/os.cc
vendored
20
3rdparty/fmt/src/os.cc
vendored
@@ -66,14 +66,14 @@ using rwresult = int;
|
||||
|
||||
// On Windows the count argument to read and write is unsigned, so convert
|
||||
// it from size_t preventing integer overflow.
|
||||
inline unsigned convert_rwcount(std::size_t count) {
|
||||
inline unsigned convert_rwcount(size_t count) {
|
||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
||||
}
|
||||
#elif FMT_USE_FCNTL
|
||||
// Return type of read and write functions.
|
||||
using rwresult = ssize_t;
|
||||
|
||||
inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
||||
inline auto convert_rwcount(size_t count) -> size_t { return count; }
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
@@ -185,7 +185,7 @@ void buffered_file::close() {
|
||||
FMT_THROW(system_error(errno, FMT_STRING("cannot close file")));
|
||||
}
|
||||
|
||||
int buffered_file::descriptor() const {
|
||||
auto buffered_file::descriptor() const -> int {
|
||||
#ifdef FMT_HAS_SYSTEM
|
||||
// fileno is a macro on OpenBSD.
|
||||
# ifdef fileno
|
||||
@@ -240,7 +240,7 @@ void file::close() {
|
||||
FMT_THROW(system_error(errno, FMT_STRING("cannot close file")));
|
||||
}
|
||||
|
||||
long long file::size() const {
|
||||
auto file::size() const -> long long {
|
||||
# ifdef _WIN32
|
||||
// Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
|
||||
// is less than 0x0500 as is the case with some default MinGW builds.
|
||||
@@ -251,7 +251,7 @@ long long file::size() const {
|
||||
if (size_lower == INVALID_FILE_SIZE) {
|
||||
DWORD error = GetLastError();
|
||||
if (error != NO_ERROR)
|
||||
FMT_THROW(windows_error(GetLastError(), "cannot get file size"));
|
||||
FMT_THROW(windows_error(error, "cannot get file size"));
|
||||
}
|
||||
unsigned long long long_size = size_upper;
|
||||
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
|
||||
@@ -266,7 +266,7 @@ long long file::size() const {
|
||||
# endif
|
||||
}
|
||||
|
||||
std::size_t file::read(void* buffer, std::size_t count) {
|
||||
auto file::read(void* buffer, size_t count) -> size_t {
|
||||
rwresult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
||||
if (result < 0)
|
||||
@@ -274,7 +274,7 @@ std::size_t file::read(void* buffer, std::size_t count) {
|
||||
return detail::to_unsigned(result);
|
||||
}
|
||||
|
||||
std::size_t file::write(const void* buffer, std::size_t count) {
|
||||
auto file::write(const void* buffer, size_t count) -> size_t {
|
||||
rwresult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
||||
if (result < 0)
|
||||
@@ -282,7 +282,7 @@ std::size_t file::write(const void* buffer, std::size_t count) {
|
||||
return detail::to_unsigned(result);
|
||||
}
|
||||
|
||||
file file::dup(int fd) {
|
||||
auto file::dup(int fd) -> file {
|
||||
// Don't retry as dup doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
||||
@@ -308,7 +308,7 @@ void file::dup2(int fd, std::error_code& ec) noexcept {
|
||||
if (result == -1) ec = std::error_code(errno, std::generic_category());
|
||||
}
|
||||
|
||||
buffered_file file::fdopen(const char* mode) {
|
||||
auto file::fdopen(const char* mode) -> buffered_file {
|
||||
// Don't retry as fdopen doesn't return EINTR.
|
||||
# if defined(__MINGW32__) && defined(_POSIX_)
|
||||
FILE* f = ::fdopen(fd_, mode);
|
||||
@@ -355,7 +355,7 @@ pipe::pipe() {
|
||||
}
|
||||
|
||||
# if !defined(__MSDOS__)
|
||||
long getpagesize() {
|
||||
auto getpagesize() -> long {
|
||||
# ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
|
||||
16
3rdparty/rcheevos/CHANGELOG.md
vendored
16
3rdparty/rcheevos/CHANGELOG.md
vendored
@@ -1,3 +1,19 @@
|
||||
# v12.1.0
|
||||
* add rc_client_get_user_subset_summary
|
||||
* add validation warning for using MeasuredIf without Measured
|
||||
* add validation warning for using ResetIf without hit targets
|
||||
* add rapi function for update_rich_presence
|
||||
* add gap to RC_CONSOLE_WII memory map to make it easier to convert pointers
|
||||
* improve range validation logic
|
||||
* fix error Remembering float value
|
||||
* fix MeasuredIf evaluation in rich presence
|
||||
* fix parsing of code notes with addresses above 0x7FFFFFFF
|
||||
* fix double evaluation of rich presence parameters
|
||||
* fix validation of SubSource chain
|
||||
* fix error if rc_client_allow_background_memory_reads called before calling rc_client_begin_load_raintegration
|
||||
* fix memory corruption when mixing legacy and new-format macros in rich presence
|
||||
* fix invalid pointer reference when iterator gets cloned
|
||||
|
||||
# v12.0.0
|
||||
* rc_client changes
|
||||
* add RC_CLIENT_EVENT_SUBSET_COMPLETED event
|
||||
|
||||
2
3rdparty/rcheevos/src/rc_client.c
vendored
2
3rdparty/rcheevos/src/rc_client.c
vendored
@@ -5880,7 +5880,7 @@ void rc_client_do_frame(rc_client_t* client)
|
||||
|
||||
richpresence = client->game->runtime.richpresence;
|
||||
if (richpresence && richpresence->richpresence)
|
||||
rc_update_richpresence(richpresence->richpresence, client->state.legacy_peek, client, NULL);
|
||||
rc_update_richpresence_internal(richpresence->richpresence, client->state.legacy_peek, client);
|
||||
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
|
||||
|
||||
@@ -223,6 +223,8 @@ static void rc_client_init_raintegration(rc_client_t* client,
|
||||
external_client->set_encore_mode_enabled(rc_client_get_encore_mode_enabled(client));
|
||||
if (external_client->set_spectator_mode_enabled)
|
||||
external_client->set_spectator_mode_enabled(rc_client_get_spectator_mode_enabled(client));
|
||||
if (external_client->set_allow_background_memory_reads)
|
||||
external_client->set_allow_background_memory_reads(client->state.allow_background_memory_reads);
|
||||
|
||||
/* attach the external client and call the callback */
|
||||
client->state.external_client = external_client;
|
||||
|
||||
2
3rdparty/rcheevos/src/rc_version.h
vendored
2
3rdparty/rcheevos/src/rc_version.h
vendored
@@ -8,7 +8,7 @@
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
#define RCHEEVOS_VERSION_MAJOR 12
|
||||
#define RCHEEVOS_VERSION_MINOR 0
|
||||
#define RCHEEVOS_VERSION_MINOR 1
|
||||
#define RCHEEVOS_VERSION_PATCH 0
|
||||
|
||||
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
||||
|
||||
4
3rdparty/rcheevos/src/rcheevos/condset.c
vendored
4
3rdparty/rcheevos/src/rcheevos/condset.c
vendored
@@ -607,8 +607,8 @@ static void rc_condset_evaluate_or_next(rc_condition_t* condition, rc_eval_state
|
||||
eval_state->or_next = rc_condset_evaluate_condition_no_add_hits(condition, eval_state);
|
||||
}
|
||||
|
||||
static void rc_test_condset_internal(rc_condition_t* condition, uint32_t num_conditions,
|
||||
rc_eval_state_t* eval_state, int can_short_circuit) {
|
||||
void rc_test_condset_internal(rc_condition_t* condition, uint32_t num_conditions,
|
||||
rc_eval_state_t* eval_state, int can_short_circuit) {
|
||||
const rc_condition_t* condition_end = condition + num_conditions;
|
||||
for (; condition < condition_end; ++condition) {
|
||||
switch (condition->type) {
|
||||
|
||||
2
3rdparty/rcheevos/src/rcheevos/rc_internal.h
vendored
2
3rdparty/rcheevos/src/rcheevos/rc_internal.h
vendored
@@ -311,6 +311,7 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse);
|
||||
int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state);
|
||||
void rc_reset_condset(rc_condset_t* self);
|
||||
rc_condition_t* rc_condset_get_conditions(rc_condset_t* self);
|
||||
void rc_test_condset_internal(rc_condition_t* condition, uint32_t num_conditions, rc_eval_state_t* eval_state, int can_short_circuit);
|
||||
|
||||
enum {
|
||||
RC_PROCESSING_COMPARE_DEFAULT = 0,
|
||||
@@ -379,6 +380,7 @@ int rc_lboard_state_active(int state);
|
||||
void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse);
|
||||
rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self);
|
||||
void rc_reset_richpresence_triggers(rc_richpresence_t* self);
|
||||
void rc_update_richpresence_internal(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud);
|
||||
|
||||
int rc_validate_memrefs(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t max_address);
|
||||
int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id);
|
||||
|
||||
156
3rdparty/rcheevos/src/rcheevos/rc_validate.c
vendored
156
3rdparty/rcheevos/src/rcheevos/rc_validate.c
vendored
@@ -133,79 +133,93 @@ static uint32_t rc_max_value(const rc_operand_t* operand)
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rc_scale_value(uint32_t value, uint8_t oper, const rc_operand_t* operand)
|
||||
static void rc_combine_ranges(uint32_t* min_val, uint32_t* max_val, uint8_t oper, uint32_t oper_min_val, uint32_t oper_max_val)
|
||||
{
|
||||
switch (oper) {
|
||||
case RC_OPERATOR_MULT:
|
||||
{
|
||||
unsigned long long scaled = ((unsigned long long)value) * rc_max_value(operand);
|
||||
if (scaled > 0xFFFFFFFF)
|
||||
return 0xFFFFFFFF;
|
||||
unsigned long long scaled = ((unsigned long long)*min_val) * oper_min_val;
|
||||
*min_val = (scaled > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)scaled;
|
||||
|
||||
return (uint32_t)scaled;
|
||||
scaled = ((unsigned long long)*max_val) * oper_max_val;
|
||||
*max_val = (scaled > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)scaled;
|
||||
break;
|
||||
}
|
||||
|
||||
case RC_OPERATOR_DIV:
|
||||
{
|
||||
const uint32_t min_val = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 1;
|
||||
return value / min_val;
|
||||
}
|
||||
*min_val = (oper_max_val == 0) ? *min_val : (*min_val / oper_max_val);
|
||||
*max_val = (oper_min_val == 0) ? *max_val : (*max_val / oper_min_val);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_AND:
|
||||
return rc_max_value(operand);
|
||||
*min_val = 0;
|
||||
*max_val &= oper_max_val;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_XOR:
|
||||
return value | rc_max_value(operand);
|
||||
*min_val = 0;
|
||||
*max_val |= oper_max_val;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_MOD:
|
||||
{
|
||||
const uint32_t divisor = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 1;
|
||||
return (divisor >= value) ? (divisor - 1) : value;
|
||||
}
|
||||
*min_val = 0;
|
||||
*max_val = (*max_val >= oper_max_val) ? oper_max_val - 1 : *max_val;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_ADD:
|
||||
{
|
||||
unsigned long scaled = ((unsigned long)value) + rc_max_value(operand);
|
||||
if (scaled > 0xFFFFFFFF)
|
||||
return 0xFFFFFFFF;
|
||||
if (*min_val > *max_val) { /* underflow occurred */
|
||||
*max_val += oper_max_val;
|
||||
}
|
||||
else {
|
||||
unsigned long scaled = ((unsigned long)*max_val) + oper_max_val;
|
||||
*max_val = (scaled > 0xFFFFFFFF) ? 0xFFFFFFFF : (uint32_t)scaled;
|
||||
}
|
||||
|
||||
return (uint32_t)scaled;
|
||||
}
|
||||
*min_val += oper_min_val;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_SUB:
|
||||
{
|
||||
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 0;
|
||||
if (value >= op_max)
|
||||
return value - op_max;
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
*min_val -= oper_max_val;
|
||||
*max_val -= oper_min_val;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_SUB_PARENT:
|
||||
{
|
||||
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : rc_max_value(operand);
|
||||
if (op_max > value)
|
||||
return op_max - value;
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
uint32_t temp = oper_min_val - *max_val;
|
||||
*max_val = oper_max_val - *min_val;
|
||||
*min_val = temp;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rc_max_chain_value(const rc_operand_t* operand)
|
||||
static void rc_chain_get_value_range(const rc_operand_t* operand, uint32_t* min_val, uint32_t* max_val)
|
||||
{
|
||||
if (rc_operand_is_memref(operand) && operand->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
||||
const rc_modified_memref_t* modified_memref = (const rc_modified_memref_t*)operand->value.memref;
|
||||
if (modified_memref->modifier_type != RC_OPERATOR_INDIRECT_READ) {
|
||||
const uint32_t op_max = rc_max_chain_value(&modified_memref->parent);
|
||||
return rc_scale_value(op_max, modified_memref->modifier_type, &modified_memref->modifier);
|
||||
if (modified_memref->modifier_type == RC_OPERATOR_DIV &&
|
||||
rc_operand_is_memref(&modified_memref->modifier) &&
|
||||
rc_operands_are_equal(&modified_memref->modifier, &modified_memref->parent)) {
|
||||
/* division by self can only return 0 or 1. */
|
||||
*min_val = 0;
|
||||
*max_val = 1;
|
||||
}
|
||||
else {
|
||||
uint32_t modifier_min_val, modifier_max_val;
|
||||
rc_chain_get_value_range(&modified_memref->parent, min_val, max_val);
|
||||
rc_chain_get_value_range(&modified_memref->modifier, &modifier_min_val, &modifier_max_val);
|
||||
rc_combine_ranges(min_val, max_val, modified_memref->modifier_type, modifier_min_val, modifier_max_val);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return rc_max_value(operand);
|
||||
*min_val = (operand->type == RC_OPERAND_CONST) ? operand->value.num : 0;
|
||||
*max_val = rc_max_value(operand);
|
||||
}
|
||||
|
||||
static int rc_validate_get_condition_index(const rc_condset_t* condset, const rc_condition_t* condition)
|
||||
@@ -291,7 +305,7 @@ static int rc_validate_range(uint32_t min_val, uint32_t max_val, char oper, uint
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rc_validate_condset_internal(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address)
|
||||
static int rc_validate_condset_internal(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address, int has_hits)
|
||||
{
|
||||
const rc_condition_t* cond;
|
||||
char buffer[128];
|
||||
@@ -299,6 +313,8 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
int in_add_hits = 0;
|
||||
int in_add_address = 0;
|
||||
int is_combining = 0;
|
||||
int has_measured = 0;
|
||||
int measuredif_index = -1;
|
||||
|
||||
if (!condset) {
|
||||
*result = '\0';
|
||||
@@ -383,6 +399,10 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
is_combining = 0;
|
||||
break;
|
||||
}
|
||||
if (!has_hits) {
|
||||
snprintf(result, result_size, "Condition %d: No captured hits to reset", index);
|
||||
return 0;
|
||||
}
|
||||
if (cond->required_hits == 1) {
|
||||
snprintf(result, result_size, "Condition %d: Hit target of 1 is redundant on ResetIf", index);
|
||||
return 0;
|
||||
@@ -398,6 +418,10 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
in_add_hits = 0;
|
||||
}
|
||||
|
||||
has_measured |= (cond->type == RC_CONDITION_MEASURED);
|
||||
if (cond->type == RC_CONDITION_MEASURED_IF && measuredif_index == -1)
|
||||
measuredif_index = index;
|
||||
|
||||
is_combining = 0;
|
||||
break;
|
||||
}
|
||||
@@ -424,10 +448,16 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
const size_t prefix_length = snprintf(result, result_size, "Condition %d: ", index);
|
||||
const rc_operand_t* operand2 = &cond->operand2;
|
||||
uint8_t oper = cond->oper;
|
||||
uint32_t max = rc_max_chain_value(operand1);
|
||||
uint32_t min, max;
|
||||
uint32_t max_val = rc_max_value(operand2);
|
||||
uint32_t min_val;
|
||||
|
||||
rc_chain_get_value_range(operand1, &min, &max);
|
||||
if (min > max) { /* underflow */
|
||||
min = 0;
|
||||
max = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if (!is_memref1) {
|
||||
/* pretend constant was on right side */
|
||||
operand2 = operand1;
|
||||
@@ -477,6 +507,7 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
break;
|
||||
}
|
||||
|
||||
/* min_val and max_val are the range allowed by operand2. max is the upper value from operand1. */
|
||||
if (!rc_validate_range(min_val, max_val, oper, max, result + prefix_length, result_size - prefix_length))
|
||||
return 0;
|
||||
}
|
||||
@@ -487,19 +518,48 @@ static int rc_validate_condset_internal(const rc_condset_t* condset, char result
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (measuredif_index != -1 && !has_measured) {
|
||||
snprintf(result, result_size, "Condition %d: MeasuredIf without Measured", measuredif_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*result = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rc_condset_has_hittargets(const rc_condset_t* condset)
|
||||
{
|
||||
if (condset->num_hittarget_conditions > 0)
|
||||
return 1;
|
||||
|
||||
/* pause and reset conditions may have hittargets and won't be classified as hittarget conditions.
|
||||
* measured conditions may also have hittargets.
|
||||
*/
|
||||
if (condset->num_pause_conditions || condset->num_reset_conditions || condset->num_measured_conditions) {
|
||||
const rc_condition_t* condition = rc_condset_get_conditions((rc_condset_t*)condset);
|
||||
/* ASSERT: don't need to add num_hittarget_conditions because it must be 0 per earlier check */
|
||||
const rc_condition_t* stop = condition + condset->num_pause_conditions
|
||||
+ condset->num_reset_conditions + condset->num_measured_conditions;
|
||||
for (; condition < stop; ++condition) {
|
||||
if (condition->required_hits)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address)
|
||||
{
|
||||
return rc_validate_condset_internal(condset, result, result_size, 0, max_address);
|
||||
int has_hits = rc_condset_has_hittargets(condset);
|
||||
return rc_validate_condset_internal(condset, result, result_size, 0, max_address, has_hits);
|
||||
}
|
||||
|
||||
int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id)
|
||||
{
|
||||
const uint32_t max_address = rc_console_max_address(console_id);
|
||||
return rc_validate_condset_internal(condset, result, result_size, console_id, max_address);
|
||||
int has_hits = rc_condset_has_hittargets(condset);
|
||||
return rc_validate_condset_internal(condset, result, result_size, console_id, max_address, has_hits);
|
||||
}
|
||||
|
||||
static int rc_validate_is_combining_condition(const rc_condition_t* condition)
|
||||
@@ -845,7 +905,7 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
|
||||
switch (compare_condition->type)
|
||||
{
|
||||
case RC_CONDITION_PAUSE_IF:
|
||||
if (conditions != compare_conditions)
|
||||
if (conditions != compare_conditions) /* PauseIf only affects conditions in same group */
|
||||
break;
|
||||
/* fallthrough */
|
||||
case RC_CONDITION_RESET_IF:
|
||||
@@ -955,10 +1015,10 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
|
||||
{
|
||||
const rc_condset_t* alt;
|
||||
int index;
|
||||
int has_hits = (trigger->requirement && trigger->requirement->num_hittarget_conditions > 0);
|
||||
int has_hits = trigger->requirement && rc_condset_has_hittargets(trigger->requirement);
|
||||
if (!has_hits) {
|
||||
for (alt = trigger->alternative; alt; alt = alt->next) {
|
||||
if (alt->num_hittarget_conditions > 0) {
|
||||
if (rc_condset_has_hittargets(alt)) {
|
||||
has_hits = 1;
|
||||
break;
|
||||
}
|
||||
@@ -966,14 +1026,14 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
|
||||
}
|
||||
|
||||
if (!trigger->alternative) {
|
||||
if (!rc_validate_condset_internal(trigger->requirement, result, result_size, console_id, max_address))
|
||||
if (!rc_validate_condset_internal(trigger->requirement, result, result_size, console_id, max_address, has_hits))
|
||||
return 0;
|
||||
|
||||
return rc_validate_conflicting_conditions(trigger->requirement, trigger->requirement, has_hits, "", "", result, result_size);
|
||||
}
|
||||
|
||||
snprintf(result, result_size, "Core ");
|
||||
if (!rc_validate_condset_internal(trigger->requirement, result + 5, result_size - 5, console_id, max_address))
|
||||
if (!rc_validate_condset_internal(trigger->requirement, result + 5, result_size - 5, console_id, max_address, has_hits))
|
||||
return 0;
|
||||
|
||||
/* compare core to itself */
|
||||
@@ -984,7 +1044,7 @@ static int rc_validate_trigger_internal(const rc_trigger_t* trigger, char result
|
||||
for (alt = trigger->alternative; alt; alt = alt->next, ++index) {
|
||||
char altname[16];
|
||||
const size_t prefix_length = snprintf(result, result_size, "Alt%d ", index);
|
||||
if (!rc_validate_condset_internal(alt, result + prefix_length, result_size - prefix_length, console_id, max_address))
|
||||
if (!rc_validate_condset_internal(alt, result + prefix_length, result_size - prefix_length, console_id, max_address, has_hits))
|
||||
return 0;
|
||||
|
||||
/* compare alt to itself */
|
||||
|
||||
@@ -723,14 +723,19 @@ rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self) {
|
||||
}
|
||||
|
||||
void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, void* unused_L) {
|
||||
rc_richpresence_display_t* display;
|
||||
(void)unused_L;
|
||||
|
||||
rc_update_richpresence_memrefs(richpresence, peek, peek_ud);
|
||||
rc_update_values(richpresence->values, peek, peek_ud);
|
||||
rc_update_richpresence_internal(richpresence, peek, peek_ud);
|
||||
}
|
||||
|
||||
void rc_update_richpresence_internal(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud) {
|
||||
rc_richpresence_display_t* display;
|
||||
|
||||
for (display = richpresence->first_display; display; display = display->next) {
|
||||
if (display->has_required_hits)
|
||||
rc_test_trigger(&display->trigger, peek, peek_ud, unused_L);
|
||||
rc_test_trigger(&display->trigger, peek, peek_ud, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
3rdparty/soundtouch/CMakeLists.txt
vendored
2
3rdparty/soundtouch/CMakeLists.txt
vendored
@@ -38,7 +38,7 @@ if(NOT "${CMAKE_BUILD_TYPE}" MATCHES "Debug")
|
||||
if(MSVC)
|
||||
target_compile_options(pcsx2-soundtouch PRIVATE /O2 /fp:fast)
|
||||
else()
|
||||
target_compile_options(pcsx2-soundtouch PRIVATE -Ofast)
|
||||
target_compile_options(pcsx2-soundtouch PRIVATE -O3 -ffast-math)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -47,7 +47,10 @@ add_subdirectory(common)
|
||||
|
||||
# make pcsx2
|
||||
add_subdirectory(pcsx2)
|
||||
add_subdirectory(pcsx2-qt)
|
||||
|
||||
if(ENABLE_QT_UI)
|
||||
add_subdirectory(pcsx2-qt)
|
||||
endif()
|
||||
|
||||
# Updater is Windows only for now.
|
||||
if (WIN32)
|
||||
@@ -62,9 +65,6 @@ endif()
|
||||
|
||||
# gsrunner
|
||||
if(ENABLE_GSRUNNER)
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
message(WARNING "GSRunner is only supported on Windows and macOS and may not build on your system")
|
||||
endif()
|
||||
add_subdirectory(pcsx2-gsrunner)
|
||||
else()
|
||||
add_subdirectory(pcsx2-gsrunner EXCLUDE_FROM_ALL)
|
||||
|
||||
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
|
||||
|
||||
†---------------------†
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
@@ -175,7 +175,6 @@
|
||||
030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000c0160000e105000000000000,Dual Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows,
|
||||
030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
@@ -253,7 +252,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,
|
||||
@@ -840,6 +838,7 @@
|
||||
03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c0160000e105000000000000,XinMo Dual Arcade,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
|
||||
030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows,
|
||||
@@ -1120,6 +1119,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,
|
||||
03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c0160000e105000000040000,Ultimate Atari Fight Stick,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,platform:Mac OS X,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X,
|
||||
030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
@@ -1197,6 +1197,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 +1332,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,
|
||||
@@ -1773,6 +1775,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
|
||||
|
||||
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);
|
||||
|
||||
@@ -1197,7 +1197,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
#if !PS_NO_COLOR1
|
||||
output.c1 = alpha_blend;
|
||||
#endif
|
||||
#if PS_AFAIL == 3 && !PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
#if PS_AFAIL == 3 && PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
if (!atst_pass)
|
||||
{
|
||||
float RTa = NEEDS_RT_FOR_AFAIL ? RtTexture.Load(int3(input.p.xy, 0)).a : 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1134,7 +1134,7 @@ void ps_main()
|
||||
#else
|
||||
SV_Target0.rgb = C.rgb / 255.0f;
|
||||
#endif
|
||||
#if PS_AFAIL == 3 && !PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
#if PS_AFAIL == 3 && PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
if (!atst_pass)
|
||||
SV_Target0.a = sample_from_rt().a;
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,6 +7,7 @@ include(GNUInstallDirs)
|
||||
# Misc option
|
||||
#-------------------------------------------------------------------------------
|
||||
option(ENABLE_TESTS "Enables building the unit tests" ON)
|
||||
option(ENABLE_QT_UI "Enables building the PCSX2 Qt interface." ON)
|
||||
option(ENABLE_GSRUNNER "Enables building the GSRunner by default. It can still be built with `make pcsx2-gsrunner` otherwise." OFF)
|
||||
option(LTO_PCSX2_CORE "Enable LTO/IPO/LTCG on the subset of pcsx2 that benefits most from it but not anything else")
|
||||
option(USE_VTUNE "Plug VTUNE to profile GS JIT.")
|
||||
|
||||
@@ -107,10 +107,19 @@ disable_compiler_warnings_for_target(cubeb)
|
||||
disable_compiler_warnings_for_target(speex)
|
||||
|
||||
# Find the Qt components that we need.
|
||||
find_package(Qt6 6.7.3 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
|
||||
if(ENABLE_QT_UI)
|
||||
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)
|
||||
find_package(Qt6 COMPONENTS CorePrivate GuiPrivate WidgetsPrivate REQUIRED)
|
||||
endif()
|
||||
|
||||
# The docking system for the debugger.
|
||||
find_package(KDDockWidgets-qt6 2.3.0 REQUIRED)
|
||||
|
||||
if(WIN32)
|
||||
add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
# Demangler for the debugger.
|
||||
@@ -119,15 +128,6 @@ add_subdirectory(3rdparty/demangler EXCLUDE_FROM_ALL)
|
||||
# Symbol table parser.
|
||||
add_subdirectory(3rdparty/ccc EXCLUDE_FROM_ALL)
|
||||
|
||||
# The docking system for the debugger.
|
||||
find_package(KDDockWidgets-qt6 2.0.0 REQUIRED)
|
||||
# Add an extra include path to work around a broken include directive.
|
||||
# TODO: Remove this the next time we update KDDockWidgets.
|
||||
get_target_property(KDDOCKWIDGETS_INCLUDE_DIRECTORY KDAB::kddockwidgets INTERFACE_INCLUDE_DIRECTORIES)
|
||||
target_include_directories(KDAB::kddockwidgets INTERFACE
|
||||
${KDDOCKWIDGETS_INCLUDE_DIRECTORY}/kddockwidgets
|
||||
)
|
||||
|
||||
# Architecture-specific.
|
||||
if(_M_X86)
|
||||
add_subdirectory(3rdparty/zydis EXCLUDE_FROM_ALL)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -99,7 +99,7 @@ __ri void Log::WriteToConsole(LOGLEVEL level, ConsoleColors color, std::string_v
|
||||
static constexpr size_t BUFFER_SIZE = 512;
|
||||
|
||||
SmallStackString<BUFFER_SIZE> buffer;
|
||||
buffer.reserve(32 + message.length());
|
||||
buffer.reserve(static_cast<u32>(32 + message.length()));
|
||||
buffer.append(s_ansi_color_codes[color]);
|
||||
|
||||
if (s_log_timestamps)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
635
common/Image.cpp
635
common/Image.cpp
@@ -14,9 +14,6 @@
|
||||
#include <webp/decode.h>
|
||||
#include <webp/encode.h>
|
||||
|
||||
// Compute the address of a base type given a field offset.
|
||||
#define BASE_FROM_RECORD_FIELD(ptr, base_type, field) ((base_type*)(((char*)ptr) - offsetof(base_type, field)))
|
||||
|
||||
static bool PNGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
||||
static bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality);
|
||||
static bool PNGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||
@@ -32,6 +29,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 +48,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)
|
||||
@@ -485,6 +488,8 @@ bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||
|
||||
struct FileCallback
|
||||
{
|
||||
// Must be the first member (&this == &mgr)
|
||||
// We pass a pointer of mgr to libjpeg, and we need to be able to cast it back to FileCallback.
|
||||
jpeg_source_mgr mgr;
|
||||
|
||||
std::FILE* fp;
|
||||
@@ -496,7 +501,7 @@ bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||
.mgr = {
|
||||
.init_source = [](j_decompress_ptr cinfo) {},
|
||||
.fill_input_buffer = [](j_decompress_ptr cinfo) -> boolean {
|
||||
FileCallback* cb = BASE_FROM_RECORD_FIELD(cinfo->src, FileCallback, mgr);
|
||||
FileCallback* cb = reinterpret_cast<FileCallback*>(cinfo->src);
|
||||
cb->mgr.next_input_byte = cb->buffer.get();
|
||||
if (cb->end_of_file)
|
||||
{
|
||||
@@ -513,7 +518,7 @@ bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||
},
|
||||
.skip_input_data =
|
||||
[](j_decompress_ptr cinfo, long num_bytes) {
|
||||
FileCallback* cb = BASE_FROM_RECORD_FIELD(cinfo->src, FileCallback, mgr);
|
||||
FileCallback* cb = reinterpret_cast<FileCallback*>(cinfo->src);
|
||||
const size_t skip_in_buffer = std::min<size_t>(cb->mgr.bytes_in_buffer, static_cast<size_t>(num_bytes));
|
||||
cb->mgr.next_input_byte += skip_in_buffer;
|
||||
cb->mgr.bytes_in_buffer -= skip_in_buffer;
|
||||
@@ -650,12 +655,12 @@ bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp,
|
||||
.mgr = {
|
||||
.init_destination =
|
||||
[](j_compress_ptr cinfo) {
|
||||
FileCallback* cb = BASE_FROM_RECORD_FIELD(cinfo->dest, FileCallback, mgr);
|
||||
FileCallback* cb = reinterpret_cast<FileCallback*>(cinfo->dest);
|
||||
cb->mgr.next_output_byte = cb->buffer.get();
|
||||
cb->mgr.free_in_buffer = BUFFER_SIZE;
|
||||
},
|
||||
.empty_output_buffer = [](j_compress_ptr cinfo) -> boolean {
|
||||
FileCallback* cb = BASE_FROM_RECORD_FIELD(cinfo->dest, FileCallback, mgr);
|
||||
FileCallback* cb = reinterpret_cast<FileCallback*>(cinfo->dest);
|
||||
if (!cb->write_error)
|
||||
cb->write_error |= (std::fwrite(cb->buffer.get(), 1, BUFFER_SIZE, cb->fp) != BUFFER_SIZE);
|
||||
|
||||
@@ -665,7 +670,7 @@ bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp,
|
||||
},
|
||||
.term_destination =
|
||||
[](j_compress_ptr cinfo) {
|
||||
FileCallback* cb = BASE_FROM_RECORD_FIELD(cinfo->dest, FileCallback, mgr);
|
||||
FileCallback* cb = reinterpret_cast<FileCallback*>(cinfo->dest);
|
||||
const size_t left = BUFFER_SIZE - cb->mgr.free_in_buffer;
|
||||
if (left > 0 && !cb->write_error)
|
||||
cb->write_error |= (std::fwrite(cb->buffer.get(), 1, left, cb->fp) != left);
|
||||
@@ -734,3 +739,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>
|
||||
|
||||
@@ -47,10 +47,19 @@
|
||||
|
||||
#include "svnrev.h"
|
||||
|
||||
// Down here because X11 has a lot of defines that can conflict
|
||||
#if defined(__linux__)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace GSRunner
|
||||
{
|
||||
static void InitializeConsole();
|
||||
static bool InitializeConfig();
|
||||
static void SettingsOverride();
|
||||
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
|
||||
static void DumpStats();
|
||||
|
||||
@@ -111,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;
|
||||
}
|
||||
@@ -473,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");
|
||||
@@ -560,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"))
|
||||
@@ -701,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);
|
||||
@@ -731,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"))
|
||||
@@ -805,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);
|
||||
@@ -823,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();
|
||||
@@ -854,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()
|
||||
@@ -1086,4 +1131,118 @@ void GSRunner::StopPlatformMessagePump()
|
||||
CocoaTools::StopMainThreadEventLoop();
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
static Display* s_display = nullptr;
|
||||
static Window s_window = None;
|
||||
static WindowInfo s_wi;
|
||||
static std::atomic<bool> s_shutdown_requested{false};
|
||||
|
||||
bool GSRunner::CreatePlatformWindow()
|
||||
{
|
||||
pxAssertRel(!s_display && s_window == None, "Tried to create window when there already was one!");
|
||||
|
||||
s_display = XOpenDisplay(nullptr);
|
||||
if (!s_display)
|
||||
{
|
||||
Console.Error("Failed to open X11 display");
|
||||
return false;
|
||||
}
|
||||
|
||||
int screen = DefaultScreen(s_display);
|
||||
Window root = RootWindow(s_display, screen);
|
||||
|
||||
s_window = XCreateSimpleWindow(s_display, root, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 1,
|
||||
BlackPixel(s_display, screen), WhitePixel(s_display, screen));
|
||||
|
||||
if (s_window == None)
|
||||
{
|
||||
Console.Error("Failed to create X11 window");
|
||||
XCloseDisplay(s_display);
|
||||
s_display = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
XStoreName(s_display, s_window, "PCSX2 GS Runner");
|
||||
XSelectInput(s_display, s_window, StructureNotifyMask);
|
||||
XMapWindow(s_display, s_window);
|
||||
|
||||
s_wi.type = WindowInfo::Type::X11;
|
||||
s_wi.display_connection = s_display;
|
||||
s_wi.window_handle = reinterpret_cast<void*>(s_window);
|
||||
s_wi.surface_width = WINDOW_WIDTH;
|
||||
s_wi.surface_height = WINDOW_HEIGHT;
|
||||
s_wi.surface_scale = 1.0f;
|
||||
|
||||
XFlush(s_display);
|
||||
PumpPlatformMessages();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSRunner::DestroyPlatformWindow()
|
||||
{
|
||||
if (s_display && s_window != None)
|
||||
{
|
||||
XDestroyWindow(s_display, s_window);
|
||||
s_window = None;
|
||||
}
|
||||
|
||||
if (s_display)
|
||||
{
|
||||
XCloseDisplay(s_display);
|
||||
s_display = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> GSRunner::GetPlatformWindowInfo()
|
||||
{
|
||||
WindowInfo wi;
|
||||
if (s_display && s_window != None)
|
||||
wi = s_wi;
|
||||
else
|
||||
wi.type = WindowInfo::Type::Surfaceless;
|
||||
return wi;
|
||||
}
|
||||
|
||||
void GSRunner::PumpPlatformMessages(bool forever)
|
||||
{
|
||||
if (!s_display)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
while (XPending(s_display) > 0)
|
||||
{
|
||||
XEvent event;
|
||||
XNextEvent(s_display, &event);
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
{
|
||||
const XConfigureEvent& configure = event.xconfigure;
|
||||
s_wi.surface_width = static_cast<u32>(configure.width);
|
||||
s_wi.surface_height = static_cast<u32>(configure.height);
|
||||
break;
|
||||
}
|
||||
case DestroyNotify:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_shutdown_requested.load())
|
||||
return;
|
||||
|
||||
if (forever)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (forever && !s_shutdown_requested.load());
|
||||
}
|
||||
|
||||
void GSRunner::StopPlatformMessagePump()
|
||||
{
|
||||
s_shutdown_requested.store(true);
|
||||
}
|
||||
#endif // _WIN32 / __APPLE__
|
||||
|
||||
@@ -73,7 +73,6 @@ def run_regression_test(runner, dumpdir, renderer, upscale, renderhacks, paralle
|
||||
#print("Running '%s'" % (" ".join(args)))
|
||||
subprocess.run(args, env=environ, stdin=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL, creationflags=creationflags)
|
||||
|
||||
|
||||
def run_regression_tests(runner, gsdir, dumpdir, renderer, upscale, renderhacks, parallel=1):
|
||||
paths = glob.glob(gsdir + "/*.*", recursive=True)
|
||||
gamepaths = list(filter(lambda x: get_gs_name(x) is not None, paths))
|
||||
@@ -104,12 +103,12 @@ def run_regression_tests(runner, gsdir, dumpdir, renderer, upscale, renderhacks,
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate frame dump images for regression tests")
|
||||
parser.add_argument("-runner", action="store", required=True, help="Path to PCSX2 GS runner")
|
||||
parser.add_argument("-gsdir", action="store", required=True, help="Directory containing GS dumps")
|
||||
parser.add_argument("-dumpdir", action="store", required=True, help="Base directory to dump frames to")
|
||||
parser.add_argument("-renderer", action="store", required=False, help="Renderer to use")
|
||||
parser.add_argument("-runner", action="store", required=True, type=str.strip, help="Path to PCSX2 GS runner")
|
||||
parser.add_argument("-gsdir", action="store", required=True, type=str.strip, help="Directory containing GS dumps")
|
||||
parser.add_argument("-dumpdir", action="store", required=True, type=str.strip, help="Base directory to dump frames to")
|
||||
parser.add_argument("-renderer", action="store", required=False, type=str.strip, help="Renderer to use")
|
||||
parser.add_argument("-upscale", action="store", type=float, default=1, help="Upscaling multiplier to use")
|
||||
parser.add_argument("-renderhacks", action="store", required=False, help="Enable HW Rendering hacks")
|
||||
parser.add_argument("-renderhacks", action="store", required=False, type=str.strip, help="Enable HW Rendering hacks")
|
||||
parser.add_argument("-parallel", action="store", type=int, default=1, help="Number of processes to run")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "common/SmallString.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QString>
|
||||
#include <QtGui/QDesktopServices>
|
||||
#include <QtWidgets/QDialog>
|
||||
@@ -134,12 +135,16 @@ void AboutDialog::showHTMLDialog(QWidget* parent, const QString& title, const QS
|
||||
tb->setOpenExternalLinks(true);
|
||||
|
||||
QFile file(path);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
if (const QByteArray data = file.readAll(); !data.isEmpty())
|
||||
tb->setText(QString::fromUtf8(data));
|
||||
else
|
||||
QFileInfo fi(path);
|
||||
if (!fi.exists() || !fi.isReadable())
|
||||
{
|
||||
tb->setText(tr("File not found: %1").arg(path));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tb->setSource(QUrl::fromLocalFile(path));
|
||||
}
|
||||
|
||||
layout->addWidget(tb, 1);
|
||||
|
||||
QDialogButtonBox* bb = new QDialogButtonBox(QDialogButtonBox::Close, &dialog);
|
||||
|
||||
@@ -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)
|
||||
@@ -281,6 +289,7 @@ target_link_libraries(pcsx2-qt PRIVATE
|
||||
PCSX2
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::GuiPrivate
|
||||
Qt6::Widgets
|
||||
KDAB::kddockwidgets
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
</action>
|
||||
<action name="actionAnalyse">
|
||||
<property name="icon">
|
||||
<iconset theme="magnifier-line"/>
|
||||
<iconset theme="search-line"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Analyze</string>
|
||||
|
||||
@@ -118,11 +118,11 @@ void DisassemblyView::contextPasteInstructionText()
|
||||
// split text in clipboard by new lines
|
||||
QString clipboardText = QApplication::clipboard()->text();
|
||||
std::vector<std::string> newInstructions = StringUtil::splitOnNewLine(clipboardText.toLocal8Bit().constData());
|
||||
int newInstructionsSize = newInstructions.size();
|
||||
u32 newInstructionsSize = static_cast<u32>(newInstructions.size());
|
||||
|
||||
// validate new instructions before pasting them
|
||||
std::vector<u32> encodedInstructions;
|
||||
for (int instructionIdx = 0; instructionIdx < newInstructionsSize; instructionIdx++)
|
||||
for (u32 instructionIdx = 0; instructionIdx < newInstructionsSize; instructionIdx++)
|
||||
{
|
||||
u32 replaceAddress = m_selectedAddressStart + instructionIdx * 4;
|
||||
u32 encodedInstruction;
|
||||
@@ -137,7 +137,7 @@ void DisassemblyView::contextPasteInstructionText()
|
||||
}
|
||||
|
||||
// paste validated instructions
|
||||
for (int instructionIdx = 0; instructionIdx < newInstructionsSize; instructionIdx++)
|
||||
for (u32 instructionIdx = 0; instructionIdx < newInstructionsSize; instructionIdx++)
|
||||
{
|
||||
u32 replaceAddress = m_selectedAddressStart + instructionIdx * 4;
|
||||
setInstructions(replaceAddress, replaceAddress, encodedInstructions[instructionIdx]);
|
||||
@@ -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)
|
||||
@@ -130,12 +144,12 @@ void DockMenuBar::onLockStateChanged(bool layout_locked)
|
||||
if (layout_locked)
|
||||
{
|
||||
m_layout_locked_toggle->setText(tr("Layout Locked"));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("padlock-lock")));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("lock-fill")));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layout_locked_toggle->setText(tr("Layout Unlocked"));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("padlock-unlock")));
|
||||
m_layout_locked_toggle->setIcon(QIcon::fromTheme(QString::fromUtf8("lock-unlock-fill")));
|
||||
}
|
||||
|
||||
m_ignore_lock_state_changed = false;
|
||||
@@ -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>
|
||||
|
||||
@@ -50,6 +50,8 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
const s32 charWidth = painter.fontMetrics().averageCharWidth();
|
||||
const s32 x = charWidth; // Left padding
|
||||
const s32 y = rowHeight;
|
||||
const s32 displayTypeWidth = MemoryViewTypeWidth[static_cast<s32>(displayType)];
|
||||
const s32 displayTypeVisualWidth = MemoryViewTypeVisualWidth[static_cast<s32>(displayType)];
|
||||
rowVisible = (height / rowHeight);
|
||||
rowCount = rowVisible + 1;
|
||||
|
||||
@@ -69,23 +71,32 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
const u32 currentRowAddress = startAddress + (i * 0x10);
|
||||
s32 valX = valuexAxis;
|
||||
segmentXAxis[0] = valX;
|
||||
for (int j = 0; j < 16 / static_cast<s32>(displayType); j++)
|
||||
for (int j = 0; j < 16 / displayTypeWidth; j++)
|
||||
{
|
||||
valX += charWidth;
|
||||
const u32 thisSegmentsStart = currentRowAddress + (j * static_cast<s32>(displayType));
|
||||
const u32 thisSegmentsStart = currentRowAddress + (j * displayTypeWidth);
|
||||
|
||||
segmentXAxis[j] = valX;
|
||||
|
||||
bool penDefault = false;
|
||||
if ((selectedAddress & ~0xF) == currentRowAddress)
|
||||
{
|
||||
if (selectedAddress >= thisSegmentsStart && selectedAddress < (thisSegmentsStart + static_cast<s32>(displayType)))
|
||||
if (selectedAddress >= thisSegmentsStart && selectedAddress < (thisSegmentsStart + displayTypeWidth))
|
||||
{ // If the current byte and row we are drawing is selected
|
||||
if (!selectedText)
|
||||
{
|
||||
s32 charsIntoSegment = ((selectedAddress - thisSegmentsStart) * 2) + ((selectedNibbleHI ? 0 : 1) ^ littleEndian);
|
||||
s32 charsIntoSegment = 0;
|
||||
if (displayType == MemoryViewType::FLOAT)
|
||||
{
|
||||
charsIntoSegment = selectedIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
charsIntoSegment = ((selectedAddress - thisSegmentsStart) * 2) + ((selectedNibbleHI ? 0 : 1) ^ littleEndian);
|
||||
}
|
||||
|
||||
if (littleEndian)
|
||||
charsIntoSegment = (static_cast<s32>(displayType) * 2) - charsIntoSegment - 1;
|
||||
charsIntoSegment = displayTypeVisualWidth - charsIntoSegment - 1;
|
||||
painter.setPen(QColor::fromRgb(205, 165, 0)); // SELECTED NIBBLE LINE COLOUR
|
||||
const QPoint lineStart(valX + (charsIntoSegment * charWidth) + 1, y + (rowHeight * i));
|
||||
painter.drawLine(lineStart, lineStart + QPoint(charWidth - 3, 0));
|
||||
@@ -139,8 +150,19 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????????????");
|
||||
break;
|
||||
}
|
||||
case MemoryViewType::FLOAT:
|
||||
{
|
||||
const u32 intVal = convertEndian<u32>(cpu.read32(thisSegmentsStart, valid));
|
||||
float val = 0.0;
|
||||
std::memcpy(&val, &intVal, sizeof(val));
|
||||
if (penDefault && val == 0.0)
|
||||
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
|
||||
QString floatStr = QString::number(val, 'g');
|
||||
painter.drawText(valX, y + (rowHeight * i), valid ? QString("%1").arg(floatStr, displayTypeVisualWidth) : "??????????????");
|
||||
break;
|
||||
}
|
||||
}
|
||||
valX += charWidth * 2 * static_cast<s32>(displayType);
|
||||
valX += charWidth * displayTypeVisualWidth;
|
||||
}
|
||||
|
||||
// valX is our new X position after the hex values
|
||||
@@ -183,7 +205,9 @@ void MemoryViewTable::SelectAt(QPoint pos)
|
||||
const u32 selectedRow = (pos.y() - 2) / (rowHeight);
|
||||
const s32 x = pos.x();
|
||||
const s32 avgSegmentWidth = segmentXAxis[1] - segmentXAxis[0];
|
||||
const u32 nibbleWidth = (avgSegmentWidth / (2 * (s32)displayType));
|
||||
const s32 displayTypeWidth = MemoryViewTypeWidth[static_cast<s32>(displayType)];
|
||||
const s32 displayTypeVisualWidth = MemoryViewTypeVisualWidth[static_cast<s32>(displayType)];
|
||||
const u32 nibbleWidth = (avgSegmentWidth / displayTypeVisualWidth);
|
||||
selectedAddress = (selectedRow * 0x10) + startAddress;
|
||||
|
||||
if (x <= segmentXAxis[0])
|
||||
@@ -191,7 +215,7 @@ void MemoryViewTable::SelectAt(QPoint pos)
|
||||
// The user clicked before the first segment
|
||||
selectedText = false;
|
||||
if (littleEndian)
|
||||
selectedAddress += static_cast<s32>(displayType) - 1;
|
||||
selectedAddress += displayTypeWidth - 1;
|
||||
selectedNibbleHI = true;
|
||||
}
|
||||
else if (x > valuexAxis && x < textXAxis)
|
||||
@@ -200,13 +224,23 @@ void MemoryViewTable::SelectAt(QPoint pos)
|
||||
// The user clicked inside of the hexadecimal area
|
||||
for (s32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (i == ((16 / static_cast<s32>(displayType)) - 1) || (x >= segmentXAxis[i] && x < (segmentXAxis[i + 1])))
|
||||
if (i == ((16 / displayTypeWidth) - 1) || (x >= segmentXAxis[i] && x < (segmentXAxis[i + 1])))
|
||||
{
|
||||
u32 indexInSegment = (x - segmentXAxis[i]) / nibbleWidth;
|
||||
if (littleEndian)
|
||||
indexInSegment = (static_cast<s32>(displayType) * 2) - indexInSegment - 1;
|
||||
selectedAddress = selectedAddress + i * static_cast<s32>(displayType) + (indexInSegment / 2);
|
||||
selectedNibbleHI = littleEndian ? indexInSegment & 1 : !(indexInSegment & 1);
|
||||
indexInSegment = displayTypeVisualWidth - indexInSegment - 1;
|
||||
selectedIndex = indexInSegment;
|
||||
if (displayType == MemoryViewType::FLOAT)
|
||||
{
|
||||
// Selecting float always points to starting address of float
|
||||
selectedAddress = selectedAddress + i * displayTypeWidth;
|
||||
selectedNibbleHI = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedAddress = selectedAddress + i * displayTypeWidth + (indexInSegment / 2);
|
||||
selectedNibbleHI = littleEndian ? indexInSegment & 1 : !(indexInSegment & 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -236,6 +270,9 @@ u128 MemoryViewTable::GetSelectedSegment(DebugInterface& cpu)
|
||||
case MemoryViewType::DWORD:
|
||||
val._u64[0] = convertEndian(cpu.read64(selectedAddress & ~7));
|
||||
break;
|
||||
case MemoryViewType::FLOAT:
|
||||
val.lo = convertEndian(cpu.read32(selectedAddress & ~3));
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@@ -260,36 +297,111 @@ void MemoryViewTable::InsertIntoSelectedHexView(u8 value, DebugInterface& cpu)
|
||||
});
|
||||
}
|
||||
|
||||
bool MemoryViewTable::InsertFloatIntoSelectedHexView(DebugInterface& cpu)
|
||||
{
|
||||
// Get currently selected float as string
|
||||
const u32 currentIntVal = GetSelectedSegment(cpu).lo;
|
||||
float currentFloatVal = 0;
|
||||
std::memcpy(¤tFloatVal, ¤tIntVal, sizeof(currentFloatVal));
|
||||
const QString currentfloatStr = QString("%1").arg(QString::number(currentFloatVal, 'g'), 14).trimmed();
|
||||
|
||||
// Prompt user to enter a new float value
|
||||
bool isValidInput = false;
|
||||
QString newFloatStr = QInputDialog::getText(parent, tr("Input New Float"), "",
|
||||
QLineEdit::Normal, currentfloatStr, &isValidInput);
|
||||
if (!isValidInput)
|
||||
return false;
|
||||
|
||||
// Convert string into float value
|
||||
bool isValidFloat = false;
|
||||
const float newFloatVal = newFloatStr.toFloat(&isValidFloat);
|
||||
if (!isValidFloat)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Input Error"), tr("Invalid float value"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write new float value back to memory
|
||||
u32 newIntVal = 0;
|
||||
std::memcpy(&newIntVal, &newFloatVal, sizeof(newIntVal));
|
||||
newIntVal = convertEndian(newIntVal);
|
||||
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
|
||||
cpu.write32(address, val);
|
||||
|
||||
QtHost::RunOnUIThread([table] {
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
table->parent->update();
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MemoryViewTable::InsertAtCurrentSelection(const QString& text, DebugInterface& cpu)
|
||||
{
|
||||
if (!cpu.isValidAddress(selectedAddress))
|
||||
return;
|
||||
|
||||
// If pasting into the hex view, also decode the input as hex bytes.
|
||||
// This approach prevents one from pasting on a nibble boundary, but that is almost always
|
||||
// user error, and we don't have an undo function in this view, so best to stay conservative.
|
||||
QByteArray input = selectedText ? text.toUtf8() : QByteArray::fromHex(text.toUtf8());
|
||||
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
const MemoryViewType display_type = displayType;
|
||||
const bool little_endian = littleEndian;
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, input, display_type, little_endian] {
|
||||
u32 currAddr = address;
|
||||
for (int i = 0; i < input.size(); i++)
|
||||
if (displayType == MemoryViewType::FLOAT)
|
||||
{
|
||||
// Convert string into float value
|
||||
bool isValidFloat = false;
|
||||
const float newFloatVal = text.toFloat(&isValidFloat);
|
||||
if (!isValidFloat)
|
||||
{
|
||||
cpu.write8(currAddr, input[i]);
|
||||
currAddr = nextAddress(currAddr, address, display_type, little_endian);
|
||||
QMessageBox::warning(parent, tr("Input Error"), tr("Invalid float value"));
|
||||
return;
|
||||
}
|
||||
|
||||
u32 end_address = address + input.size();
|
||||
QtHost::RunOnUIThread([table, end_address] {
|
||||
if (!table)
|
||||
return;
|
||||
// Write new float value back to memory
|
||||
u32 newIntVal = 0;
|
||||
std::memcpy(&newIntVal, &newFloatVal, sizeof(newIntVal));
|
||||
newIntVal = convertEndian(newIntVal);
|
||||
|
||||
table->UpdateSelectedAddress(end_address);
|
||||
table->parent->update();
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
|
||||
cpu.write32(address, val);
|
||||
|
||||
QtHost::RunOnUIThread([table] {
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
table->parent->update();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// If pasting into the hex view, also decode the input as hex bytes.
|
||||
// This approach prevents one from pasting on a nibble boundary, but that is almost always
|
||||
// user error, and we don't have an undo function in this view, so best to stay conservative.
|
||||
QByteArray input = selectedText ? text.toUtf8() : QByteArray::fromHex(text.toUtf8());
|
||||
|
||||
const QPointer<MemoryViewTable> table(this);
|
||||
const MemoryViewType display_type = displayType;
|
||||
const bool little_endian = littleEndian;
|
||||
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, input, display_type, little_endian] {
|
||||
u32 currAddr = address;
|
||||
for (int i = 0; i < input.size(); i++)
|
||||
{
|
||||
cpu.write8(currAddr, input[i]);
|
||||
currAddr = nextAddress(currAddr, address, display_type, little_endian);
|
||||
}
|
||||
|
||||
u32 end_address = address + input.size();
|
||||
QtHost::RunOnUIThread([table, end_address] {
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
table->UpdateSelectedAddress(end_address);
|
||||
table->parent->update();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
u32 MemoryViewTable::nextAddress(u32 addr, u32 selected_address, MemoryViewType display_type, bool little_endian)
|
||||
@@ -300,8 +412,8 @@ u32 MemoryViewTable::nextAddress(u32 addr, u32 selected_address, MemoryViewType
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selected_address % static_cast<s32>(display_type) == 0)
|
||||
return addr + (static_cast<s32>(display_type) * 2 - 1);
|
||||
if (selected_address % MemoryViewTypeWidth[static_cast<s32>(display_type)] == 0)
|
||||
return addr + (MemoryViewTypeWidth[static_cast<s32>(display_type)] * 2 - 1);
|
||||
else
|
||||
return addr - 1;
|
||||
}
|
||||
@@ -317,7 +429,7 @@ u32 MemoryViewTable::prevAddress(u32 addr, u32 selected_address, MemoryViewType
|
||||
{
|
||||
// It works
|
||||
if ((addr & (static_cast<u32>(display_type) - 1)) == (static_cast<u32>(display_type) - 1))
|
||||
return addr - (static_cast<s32>(display_type) * 2 - 1);
|
||||
return addr - (MemoryViewTypeWidth[static_cast<s32>(display_type)] * 2 - 1);
|
||||
else
|
||||
return selected_address + 1;
|
||||
}
|
||||
@@ -325,39 +437,104 @@ u32 MemoryViewTable::prevAddress(u32 addr, u32 selected_address, MemoryViewType
|
||||
|
||||
void MemoryViewTable::ForwardSelection()
|
||||
{
|
||||
if (!littleEndian)
|
||||
if (displayType == MemoryViewType::FLOAT)
|
||||
{
|
||||
if ((selectedNibbleHI = !selectedNibbleHI))
|
||||
UpdateSelectedAddress(selectedAddress + 1);
|
||||
if (!littleEndian)
|
||||
{
|
||||
// Bump to next address if selection is at end of current float segment
|
||||
if (selectedIndex >= MemoryViewTypeVisualWidth[static_cast<s32>(MemoryViewType::FLOAT)] - 1)
|
||||
{
|
||||
UpdateSelectedAddress(selectedAddress + 4);
|
||||
selectedIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndex++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectedIndex <= 0)
|
||||
{
|
||||
UpdateSelectedAddress(selectedAddress + 4);
|
||||
selectedIndex = MemoryViewTypeVisualWidth[static_cast<s32>(MemoryViewType::FLOAT)] - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndex--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((selectedNibbleHI = !selectedNibbleHI))
|
||||
if (!littleEndian)
|
||||
{
|
||||
if (selectedAddress % static_cast<s32>(displayType) == 0)
|
||||
UpdateSelectedAddress(selectedAddress + (static_cast<s32>(displayType) * 2 - 1));
|
||||
else
|
||||
UpdateSelectedAddress(selectedAddress - 1);
|
||||
if ((selectedNibbleHI = !selectedNibbleHI))
|
||||
UpdateSelectedAddress(selectedAddress + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((selectedNibbleHI = !selectedNibbleHI))
|
||||
{
|
||||
if (selectedAddress % MemoryViewTypeWidth[static_cast<s32>(displayType)] == 0)
|
||||
UpdateSelectedAddress(selectedAddress + (MemoryViewTypeVisualWidth[static_cast<s32>(displayType)] - 1));
|
||||
else
|
||||
UpdateSelectedAddress(selectedAddress - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryViewTable::BackwardSelection()
|
||||
{
|
||||
if (!littleEndian)
|
||||
const s32 displayTypeWidth = MemoryViewTypeWidth[static_cast<s32>(displayType)];
|
||||
const s32 displayTypeVisualWidth = MemoryViewTypeVisualWidth[static_cast<s32>(displayType)];
|
||||
|
||||
if (displayType == MemoryViewType::FLOAT)
|
||||
{
|
||||
if (!(selectedNibbleHI = !selectedNibbleHI))
|
||||
UpdateSelectedAddress(selectedAddress - 1);
|
||||
if (!littleEndian)
|
||||
{
|
||||
// Bump to previous address if selection is at beginning of current float segment
|
||||
if (selectedIndex <= 0)
|
||||
{
|
||||
UpdateSelectedAddress(selectedAddress - 4);
|
||||
selectedIndex = displayTypeVisualWidth - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndex--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectedIndex >= displayTypeVisualWidth - 1)
|
||||
{
|
||||
UpdateSelectedAddress(selectedAddress - 4);
|
||||
selectedIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(selectedNibbleHI = !selectedNibbleHI))
|
||||
if (!littleEndian)
|
||||
{
|
||||
// It works
|
||||
if ((selectedAddress & (static_cast<u32>(displayType) - 1)) == (static_cast<u32>(displayType) - 1))
|
||||
UpdateSelectedAddress(selectedAddress - (static_cast<s32>(displayType) * 2 - 1));
|
||||
else
|
||||
UpdateSelectedAddress(selectedAddress + 1);
|
||||
if (!(selectedNibbleHI = !selectedNibbleHI))
|
||||
UpdateSelectedAddress(selectedAddress - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(selectedNibbleHI = !selectedNibbleHI))
|
||||
{
|
||||
// It works
|
||||
if ((selectedAddress & (static_cast<u32>(displayTypeWidth) - 1)) == (static_cast<u32>(displayTypeWidth) - 1))
|
||||
UpdateSelectedAddress(selectedAddress - (displayTypeVisualWidth - 1));
|
||||
else
|
||||
UpdateSelectedAddress(selectedAddress + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,12 +607,15 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar, DebugInterface& cpu)
|
||||
|
||||
if (keyCharIsText)
|
||||
{
|
||||
// Check if key pressed is hex before insertion (QString conversion fails otherwise)
|
||||
const u8 keyPressed = static_cast<u8>(QString(QChar(key)).toInt(&pressHandled, 16));
|
||||
if (pressHandled)
|
||||
if (displayType != MemoryViewType::FLOAT)
|
||||
{
|
||||
InsertIntoSelectedHexView(keyPressed, cpu);
|
||||
ForwardSelection();
|
||||
// Check if key pressed is hex before insertion (QString conversion fails otherwise)
|
||||
const u8 keyPressed = static_cast<u8>(QString(QChar(key)).toInt(&pressHandled, 16));
|
||||
if (pressHandled)
|
||||
{
|
||||
InsertIntoSelectedHexView(keyPressed, cpu);
|
||||
ForwardSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +635,13 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar, DebugInterface& cpu)
|
||||
BackwardSelection();
|
||||
pressHandled = true;
|
||||
break;
|
||||
case Qt::Key::Key_Return:
|
||||
case Qt::Key::Key_Enter:
|
||||
if (displayType == MemoryViewType::FLOAT)
|
||||
{
|
||||
pressHandled = InsertFloatIntoSelectedHexView(cpu);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -549,7 +736,8 @@ bool MemoryView::fromJson(const JsonValueWrapper& json)
|
||||
if (type == MemoryViewType::BYTE ||
|
||||
type == MemoryViewType::BYTEHW ||
|
||||
type == MemoryViewType::WORD ||
|
||||
type == MemoryViewType::DWORD)
|
||||
type == MemoryViewType::DWORD ||
|
||||
type == MemoryViewType::FLOAT)
|
||||
m_table.SetViewType(type);
|
||||
}
|
||||
|
||||
@@ -647,6 +835,12 @@ void MemoryView::openContextMenu(QPoint pos)
|
||||
connect(dword_action, &QAction::triggered, this, [this]() { m_table.SetViewType(MemoryViewType::DWORD); });
|
||||
view_type_group->addAction(dword_action);
|
||||
|
||||
QAction* float_action = menu->addAction(tr("Show as float"));
|
||||
float_action->setCheckable(true);
|
||||
float_action->setChecked(current_view_type == MemoryViewType::FLOAT);
|
||||
connect(float_action, &QAction::triggered, this, [this]() { m_table.SetViewType(MemoryViewType::FLOAT); });
|
||||
view_type_group->addAction(float_action);
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
createEventActions<DebuggerEvents::AddToSavedAddresses>(menu, [this]() {
|
||||
@@ -655,9 +849,16 @@ void MemoryView::openContextMenu(QPoint pos)
|
||||
return std::optional(event);
|
||||
});
|
||||
|
||||
connect(menu->addAction(tr("Copy Byte")), &QAction::triggered, this, &MemoryView::contextCopyByte);
|
||||
QAction* copy_byte_action = menu->addAction(tr("Copy Byte"));
|
||||
copy_byte_action->setEnabled(current_view_type != MemoryViewType::FLOAT);
|
||||
connect(copy_byte_action, &QAction::triggered, this, &MemoryView::contextCopyByte);
|
||||
|
||||
connect(menu->addAction(tr("Copy Segment")), &QAction::triggered, this, &MemoryView::contextCopySegment);
|
||||
connect(menu->addAction(tr("Copy Character")), &QAction::triggered, this, &MemoryView::contextCopyCharacter);
|
||||
|
||||
QAction* copy_char_action = menu->addAction(tr("Copy Character"));
|
||||
copy_char_action->setEnabled(current_view_type != MemoryViewType::FLOAT);
|
||||
connect(copy_char_action, &QAction::triggered, this, &MemoryView::contextCopyCharacter);
|
||||
|
||||
connect(menu->addAction(tr("Paste")), &QAction::triggered, this, &MemoryView::contextPaste);
|
||||
|
||||
menu->popup(this->mapToGlobal(pos));
|
||||
@@ -673,7 +874,17 @@ void MemoryView::contextCopyByte()
|
||||
|
||||
void MemoryView::contextCopySegment()
|
||||
{
|
||||
QApplication::clipboard()->setText(QString::number(m_table.GetSelectedSegment(cpu()).lo, 16).toUpper());
|
||||
if (m_table.GetViewType() == MemoryViewType::FLOAT)
|
||||
{
|
||||
u32 intVal = m_table.GetSelectedSegment(cpu()).lo;
|
||||
float val = 0;
|
||||
std::memcpy(&val, &intVal, sizeof(val));
|
||||
QApplication::clipboard()->setText(QString::number(val, 'g'));
|
||||
}
|
||||
else
|
||||
{
|
||||
QApplication::clipboard()->setText(QString::number(m_table.GetSelectedSegment(cpu()).lo, 16).toUpper());
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryView::contextCopyCharacter()
|
||||
|
||||
@@ -20,10 +20,27 @@
|
||||
|
||||
enum class MemoryViewType
|
||||
{
|
||||
BYTE = 1,
|
||||
BYTEHW = 2,
|
||||
WORD = 4,
|
||||
DWORD = 8,
|
||||
BYTE = 0,
|
||||
BYTEHW = 1,
|
||||
WORD = 2,
|
||||
DWORD = 3,
|
||||
FLOAT = 4,
|
||||
};
|
||||
|
||||
const s32 MemoryViewTypeWidth[] = {
|
||||
1, // BYTE
|
||||
2, // BYTEHW
|
||||
4, // WORD
|
||||
8, // DWORD
|
||||
4, // FLOAT
|
||||
};
|
||||
|
||||
const s32 MemoryViewTypeVisualWidth[] = {
|
||||
2, // BYTE
|
||||
4, // BYTEHW
|
||||
8, // WORD
|
||||
16, // DWORD
|
||||
14, // FLOAT
|
||||
};
|
||||
|
||||
class MemoryViewTable : public QObject
|
||||
@@ -48,6 +65,7 @@ private:
|
||||
bool selectedNibbleHI = false;
|
||||
|
||||
void InsertIntoSelectedHexView(u8 value, DebugInterface& cpu);
|
||||
bool InsertFloatIntoSelectedHexView(DebugInterface& cpu);
|
||||
|
||||
template <class T>
|
||||
T convertEndian(T in)
|
||||
@@ -73,6 +91,7 @@ public:
|
||||
|
||||
u32 startAddress;
|
||||
u32 selectedAddress;
|
||||
s32 selectedIndex;
|
||||
|
||||
void UpdateStartAddress(u32 start);
|
||||
void UpdateSelectedAddress(u32 selected, bool page = false);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user