Compare commits
380 commits
Author | SHA1 | Date | |
---|---|---|---|
|
b798d8f1aa | ||
|
049ec4af90 | ||
|
162d742cc0 | ||
|
8c1f75ab8c | ||
|
d2c09dfaff | ||
|
3292833fb8 | ||
|
04c5a9f1b2 | ||
|
c5cc94c4b7 | ||
|
64513395f3 | ||
|
e6e6313219 | ||
|
4e2872f248 | ||
|
2d31bf5685 | ||
|
9bcd738f5c | ||
|
3bf5ded0d2 | ||
|
a3e840526a | ||
|
54c42f9c27 | ||
|
b4ae19411b | ||
|
37230107f4 | ||
|
730fa67952 | ||
|
3cf2f41723 | ||
|
ba3c693717 | ||
|
0687e59bda | ||
|
576658b6eb | ||
|
c7504e7016 | ||
|
e4a028834a | ||
|
f36062a94e | ||
|
9ef7f54f19 | ||
|
003518c234 | ||
|
6f2225fb61 | ||
|
f80a77fa27 | ||
|
ea3774cece | ||
|
58bd87666e | ||
|
fbadacae78 | ||
|
ceef7af1da | ||
|
ece18d10c5 | ||
|
ae9023ddf3 | ||
|
3f0abccb59 | ||
|
104c82c2c3 | ||
|
2cb6ce635f | ||
|
4ce001aef3 | ||
|
1fca8ae6bf | ||
|
3ffd20b833 | ||
|
9411e40c20 | ||
|
03d7af2efc | ||
|
9020959511 | ||
|
98d1c71981 | ||
|
741e971681 | ||
|
2d477f80b0 | ||
|
2311c8d287 | ||
|
32b09193d1 | ||
|
4afa41b927 | ||
|
3ab3e4be06 | ||
|
f4e93df1b1 | ||
|
115ba4433c | ||
|
74064af730 | ||
|
62d7a73381 | ||
|
d176109d3b | ||
|
6eddc0b982 | ||
|
346f0f945d | ||
|
de6a8fba51 | ||
|
5c41a48e39 | ||
|
19c03aff4d | ||
|
fffa44911c | ||
|
10fea83b4a | ||
|
eea4159756 | ||
|
e5cec05633 | ||
|
a1d69982f3 | ||
|
e3cb3d029b | ||
|
27fc7de07a | ||
|
a1e5bb7bc0 | ||
|
61de096d26 | ||
|
4f00a7c7c1 | ||
|
3420af829c | ||
|
830842891e | ||
|
dd885cfe2f | ||
|
8a0400ad2c | ||
|
bcd4b918dc | ||
|
c82c007a75 | ||
|
0a470067f5 | ||
|
9734066514 | ||
|
2a86faa51e | ||
|
4bac7cb79e | ||
|
db3b689166 | ||
|
1189f53840 | ||
|
6e27b8ab91 | ||
|
3d0f038697 | ||
|
6c867859bf | ||
|
f11c31b41c | ||
|
cffafad2ca | ||
|
b6fa2cecd3 | ||
|
9c971825a9 | ||
|
c57689cc90 | ||
|
511663198e | ||
|
531b3e103a | ||
|
e422afdec1 | ||
|
ba3295930c | ||
|
4fc49ee0ca | ||
|
f6296ceb09 | ||
|
9a9ed52b70 | ||
|
44af55a77f | ||
|
72a0ba1e8e | ||
|
aeadd4c280 | ||
|
d6ab840e4b | ||
|
492a55ee8b | ||
|
541af8d5de | ||
|
7bae23d79d | ||
|
a0c06f8d9c | ||
|
814263b442 | ||
|
2f5855a7a4 | ||
|
cd694c01d8 | ||
|
c717f547cf | ||
|
8bffd9725e | ||
|
e25f287d60 | ||
|
9f0bbccd50 | ||
|
29f19d0ab6 | ||
|
58dc7562a3 | ||
|
ee6887b68a | ||
|
2bfbec3e9e | ||
|
705fe11e07 | ||
|
e73ca9e052 | ||
|
6437a5db60 | ||
|
95797b05f1 | ||
|
9939f1cd05 | ||
|
7eb7ad684c | ||
|
826f10239c | ||
|
78bb14bd23 | ||
|
b230c9c639 | ||
|
8cfd843d8f | ||
|
160f1ea8a0 | ||
|
c3ce0eece2 | ||
|
b8d86a18da | ||
|
0bf0b5c22b | ||
|
4c64e4879f | ||
|
af4eb68065 | ||
|
c775872a6c | ||
|
859f5090c8 | ||
|
38146f2023 | ||
|
a0fef2d5ab | ||
|
4bfb37f8fb | ||
|
965da856db | ||
|
34fdbafe85 | ||
|
9bfc3e90cc | ||
|
9d9da94b7b | ||
|
5a4e87aba3 | ||
|
5dc0a3630a | ||
|
15fde6a51b | ||
|
ea8f3e5e58 | ||
|
89d9842c7e | ||
|
be970bcfe4 | ||
|
ec7c83a58e | ||
|
6a86c80445 | ||
|
37fa0d135c | ||
|
df9f15eb68 | ||
|
ee1a3b904e | ||
|
4bddd38d70 | ||
|
0733e173b2 | ||
|
498e7aac56 | ||
|
f7f17a077c | ||
|
0b167aad52 | ||
|
08bbb4a981 | ||
|
fbbc4943f6 | ||
|
eda32e0695 | ||
|
b764ed4682 | ||
|
2011c5511c | ||
|
3ea26cc910 | ||
|
d812463649 | ||
|
5fea81c07d | ||
|
91370ee5ac | ||
|
fa3815d681 | ||
|
90cb92bcc7 | ||
|
f2715b39ec | ||
|
d5c83a80a3 | ||
|
f96ab3afda | ||
|
d1b9473cd2 | ||
|
373c83c357 | ||
|
6a0c73b547 | ||
|
78bd0fdf3e | ||
|
31a5d8c481 | ||
|
72ac4f94db | ||
|
6f25cf31a7 | ||
|
2f5c4d819e | ||
|
b57049f1aa | ||
|
9a75af2fa9 | ||
|
0c30acb285 | ||
|
cb10c6fbf4 | ||
|
4ce1b1afed | ||
|
5bd1a492be | ||
|
e688e24eb9 | ||
|
9928d01ac4 | ||
|
cba9d00019 | ||
|
b45f9c39c7 | ||
|
1b3ca81efc | ||
|
369f62318f | ||
|
4562573711 | ||
|
ce8b1f0996 | ||
|
958fd0049c | ||
|
8772c336ec | ||
|
7d80a74dc3 | ||
|
2fcf115d0b | ||
|
2bfc408242 | ||
|
e9bfca8cca | ||
|
13d58d8ed0 | ||
|
f4aa5e1b98 | ||
|
e0620fcd40 | ||
|
bceadadcb4 | ||
|
6802f77cb9 | ||
|
af085d7e5a | ||
|
ced9ee4b0b | ||
|
dc6d6b91d4 | ||
|
5060e72b96 | ||
|
5ae32d3c70 | ||
|
953bd0919b | ||
|
b68d7c8adb | ||
|
9b2cf0abbd | ||
|
5913de947f | ||
|
3a44c3a758 | ||
|
995a34e0e3 | ||
|
f90fdf66c8 | ||
|
7bc18c8538 | ||
|
a25d5dcd2f | ||
|
cd89f62935 | ||
|
ce616f1c5c | ||
|
c137c562cd | ||
|
36d5708391 | ||
|
f6e8ebec99 | ||
|
2876713f0f | ||
|
ef4c00a896 | ||
|
7a587d927f | ||
|
3eed0d0613 | ||
|
788b9cd3bf | ||
|
2dfa164629 | ||
|
c1f8a525ca | ||
|
5fb5dcdd70 | ||
|
46ae3e55ea | ||
|
4ce48abfc1 | ||
|
ac4ef4f853 | ||
|
07f973076d | ||
|
8132c51a12 | ||
|
4236beabaf | ||
|
0428a93315 | ||
|
3e8ef44a1d | ||
|
901927d7fe | ||
|
94b2060979 | ||
|
06b02183cb | ||
|
2663ac9666 | ||
|
160c34ef28 | ||
|
81bca06707 | ||
|
acb355a8c3 | ||
|
f2cca01e29 | ||
|
084422355a | ||
|
063bb96e5d | ||
|
5ae6d9084a | ||
|
51480818cd | ||
|
f8c39ace1c | ||
|
bee2dabc77 | ||
|
8aa97a8118 | ||
|
2cfc39e874 | ||
|
57cb2f846e | ||
|
ecbb79c4bf | ||
|
99e81f1559 | ||
|
c6563a4656 | ||
|
4ad2d0ac2d | ||
|
51bef1b3da | ||
|
455836af89 | ||
|
cb205c4c36 | ||
|
af277d4d14 | ||
|
59773509af | ||
|
1f5a10371e | ||
|
1ca5782396 | ||
|
57883910d6 | ||
|
4ceeb58dbc | ||
|
64d3716cfd | ||
|
0c3d55a1a1 | ||
|
a5940b2e21 | ||
|
7316b011a4 | ||
|
24354cb39f | ||
|
804d90d48f | ||
|
a681386f28 | ||
|
b01c06b412 | ||
|
635ae5de31 | ||
|
d65c4efdd8 | ||
|
b5925ab139 | ||
|
03181d1179 | ||
|
96058f5d7e | ||
|
f7d7eecb6c | ||
|
44a75d6586 | ||
|
369879e685 | ||
|
aae7573e63 | ||
|
9b6021b79e | ||
|
0d9e6bd482 | ||
|
d314b25f91 | ||
|
02234715c5 | ||
|
128bab29f8 | ||
|
4dd6365a99 | ||
|
28f6358ec5 | ||
|
4da7692a2d | ||
|
1b678d0ebc | ||
|
224cb6ac8e | ||
|
231ba050a2 | ||
|
e36dbaf255 | ||
|
70c45f7cf8 | ||
|
f58fa2297e | ||
|
b0c0d6444c | ||
|
7188ab863a | ||
|
d7c78eedce | ||
|
afd619a7d8 | ||
|
0665cb5306 | ||
|
5630f3958b | ||
|
0e3668a7bb | ||
|
6512ed8a8c | ||
|
d4b0b7fc29 | ||
|
6a09d6ecda | ||
|
1bfc4b6e6c | ||
|
21aa6ead5f | ||
|
ca509a8b97 | ||
|
543704d57c | ||
|
2b7a4f8d19 | ||
|
4e97420b3b | ||
|
573b2eb529 | ||
|
9666abc172 | ||
|
9096402a30 | ||
|
dc5f85a34e | ||
|
807094d627 | ||
|
13c7b8542d | ||
|
4da1f613b6 | ||
|
df8822760a | ||
|
9113a6e6a6 | ||
|
b08ab9f712 | ||
|
d395be07ee | ||
|
89504b0184 | ||
|
f045a1742d | ||
|
8eaa1f312d | ||
|
0129679bb0 | ||
|
0166939609 | ||
|
be75a97efe | ||
|
af58740f5d | ||
|
4e588bb6c1 | ||
|
78f6e11b91 | ||
|
19ca9cb47d | ||
|
080eccd8fc | ||
|
9c4b2112ae | ||
|
fb3e290133 | ||
|
389276bb03 | ||
|
9d4789e082 | ||
|
17b0da7283 | ||
|
4b20fc6922 | ||
|
78902d7632 | ||
|
cc0ccf2648 | ||
|
f219b47e98 | ||
|
7c2488c942 | ||
|
c03b6f3d84 | ||
|
21b167d382 | ||
|
7905793ae0 | ||
|
8c5c0e6114 | ||
|
ade8bf7b3b | ||
|
9fdeeb3fb6 | ||
|
9b8d2a88de | ||
|
e1cbb50c64 | ||
|
725dcea05a | ||
|
6131ddbefe | ||
|
88b43370dc | ||
|
d62261e7a4 | ||
|
7fcf0a3283 | ||
|
313f653fe0 | ||
|
e0a9bbe600 | ||
|
d589696eff | ||
|
338d29d271 | ||
|
609fa5c7d7 | ||
|
da13579356 | ||
|
dd9788262e | ||
|
6cba825bac | ||
|
d52bf795e4 | ||
|
8f19ac2dee | ||
|
08d2586a86 | ||
|
e41f179108 | ||
|
1481c1d231 | ||
|
b9822602b2 | ||
|
f98b904c50 | ||
|
7cc47551a4 | ||
|
e34d23c8e7 |
4
.github/workflows/linux-appimage-build.yml
vendored
|
@ -64,7 +64,7 @@ jobs:
|
|||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
|
@ -135,7 +135,7 @@ jobs:
|
|||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDISABLE_SSE4=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DDISABLE_SSE4=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_PREFIX_PATH="$HOME/deps" -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" -DCMAKE_SHARED_LINKER_FLAGS_INIT="-fuse-ld=lld" ..
|
||||
cmake --build . --parallel
|
||||
cd ..
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64-SSE2
|
||||
|
|
103
.github/workflows/linux-cross-appimage-build.yml
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
name: 🐧 Linux Cross-Compiled AppImage
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build"
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
arch: ["arm64", "armhf"]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
container:
|
||||
image: ghcr.io/duckstation/cross-build-${{ matrix.arch }}:latest
|
||||
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/deps
|
||||
key: deps-cross ${{ matrix.arch }} ${{ hashFiles('scripts/deps/build-dependencies-linux.sh', 'scripts/deps/build-dependencies-linux-cross.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
scripts/deps/build-dependencies-linux.sh -skip-cleanup "$HOME/deps/host"
|
||||
scripts/deps/build-dependencies-linux-cross.sh -skip-download "$HOME/deps/host" "${{ matrix.arch }}" "/${{ matrix.arch }}-chroot" "$HOME/deps/cross"
|
||||
|
||||
# Work around container ownership issue
|
||||
- name: Set Safe Directory
|
||||
shell: bash
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
- name: Create Binary Aliases
|
||||
run: |
|
||||
ln -s llvm-strip-19 /usr/bin/llvm-strip
|
||||
|
||||
- name: Set Up Toolchain File
|
||||
run: |
|
||||
cp "$HOME/deps/cross/toolchain.cmake" "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_C_COMPILER clang-19)' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_C_COMPILER_AR llvm-ar-19)' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_C_COMPILER_RANLIB llvm-ranlib-19)' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++-19)' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_CXX_COMPILER_AR llvm-ar-19)' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_CXX_COMPILER_RANLIB llvm-ranlib-19)' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")' >> "$HOME/toolchain.cmake"
|
||||
echo 'set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")' >> "$HOME/toolchain.cmake"
|
||||
|
||||
- name: Initialize Build Tag
|
||||
run: |
|
||||
echo '#pragma once' > src/scmversion/tag.h
|
||||
|
||||
- name: Set Build Tag Asset
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_ASSET "DuckStation-${{ matrix.arch }}.AppImage"' >> src/scmversion/tag.h
|
||||
echo '#define SCM_RELEASE_TAGS {"latest", "preview"}' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Preview Release
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "preview"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Tag as Rolling Release
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
echo '#define SCM_RELEASE_TAG "latest"' >> src/scmversion/tag.h
|
||||
|
||||
- name: Download Patch Archives
|
||||
shell: bash
|
||||
run: |
|
||||
cd data/resources
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
curl -LO "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_TOOLCHAIN_FILE="$HOME/toolchain.cmake" -DLCONVERT_EXE="$HOME/deps/host/bin/lconvert" -DHOST_MIN_PAGE_SIZE=4096 -DHOST_MAX_PAGE_SIZE=16384 -DHOST_CACHE_LINE_SIZE=64 -DBUILD_QT_FRONTEND=ON -DBUILD_MINI_FRONTEND=ON
|
||||
|
||||
- name: Compile Build
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --build build --parallel
|
||||
scripts/packaging/appimage/make-cross-appimage.sh duckstation-qt ${{ matrix.arch }} "$(realpath build)" "$HOME/deps/cross" "/${{ matrix.arch }}-chroot"
|
||||
scripts/packaging/appimage/make-cross-appimage.sh -inject-libc duckstation-mini ${{ matrix.arch }} "$(realpath build)" "$HOME/deps/cross" "/${{ matrix.arch }}-chroot"
|
||||
|
||||
- name: Upload AppImages
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "linux-${{ matrix.arch }}-appimage"
|
||||
path: "DuckStation-*.AppImage"
|
21
.github/workflows/linux-flatpak-build.yml
vendored
|
@ -15,12 +15,17 @@ on:
|
|||
|
||||
jobs:
|
||||
linux-flatpak-build:
|
||||
name: "x64"
|
||||
runs-on: ubuntu-22.04
|
||||
name: "Build"
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
setup: [{arch: "x86_64", runner: "ubuntu-22.04"}, {arch: "aarch64", runner: "ubuntu-24.04-arm"}]
|
||||
|
||||
runs-on: ${{ matrix.setup.runner }}
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
|
||||
options: --privileged
|
||||
timeout-minutes: 120
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
@ -72,17 +77,17 @@ jobs:
|
|||
- name: Build Flatpak
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: duckstation-x64.flatpak
|
||||
bundle: duckstation-${{ matrix.setup.arch }}.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
arch: x86_64
|
||||
arch: ${{ matrix.setup.arch }}
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/media
|
||||
branch: stable
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/packaging/flatpak/**/*.yaml') }}
|
||||
cache-key: flatpak-${{ hashFiles('scripts/packaging/flatpak/**/*.yaml') }}
|
||||
|
||||
- name: Validate Build
|
||||
run: |
|
||||
|
@ -109,5 +114,5 @@ jobs:
|
|||
- name: Upload Flatpak
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: "linux-flatpak"
|
||||
path: "duckstation-x64.flatpak"
|
||||
name: "linux-flatpak-${{ matrix.setup.arch }}"
|
||||
path: "duckstation-${{ matrix.setup.arch }}.flatpak"
|
||||
|
|
19
.github/workflows/main.yml
vendored
|
@ -25,6 +25,9 @@ jobs:
|
|||
linux-appimage:
|
||||
name: 🐧 Linux AppImage
|
||||
uses: "./.github/workflows/linux-appimage-build.yml"
|
||||
linux-cross-appimage:
|
||||
name: 🐧 Linux Cross-Compiled AppImage
|
||||
uses: "./.github/workflows/linux-cross-appimage-build.yml"
|
||||
linux-flatpak:
|
||||
name: 📦 Linux Flatpak
|
||||
uses: "./.github/workflows/linux-flatpak-build.yml"
|
||||
|
@ -34,7 +37,7 @@ jobs:
|
|||
|
||||
create-release:
|
||||
name: 📤 Create Release
|
||||
needs: [windows, linux-appimage, linux-flatpak, macos]
|
||||
needs: [windows, linux-appimage, linux-cross-appimage, linux-flatpak, macos]
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev'
|
||||
steps:
|
||||
|
@ -63,7 +66,12 @@ jobs:
|
|||
./artifacts/windows-arm64/duckstation-windows-arm64-release-symbols.zip
|
||||
./artifacts/linux-x64-appimage/DuckStation-x64.AppImage
|
||||
./artifacts/linux-x64-sse2-appimage/DuckStation-x64-SSE2.AppImage
|
||||
./artifacts/linux-flatpak/duckstation-x64.flatpak
|
||||
./artifacts/linux-arm64-appimage/DuckStation-arm64.AppImage
|
||||
./artifacts/linux-arm64-appimage/DuckStation-Mini-arm64.AppImage
|
||||
./artifacts/linux-armhf-appimage/DuckStation-armhf.AppImage
|
||||
./artifacts/linux-armhf-appimage/DuckStation-Mini-armhf.AppImage
|
||||
./artifacts/linux-flatpak-x86_64/duckstation-x86_64.flatpak
|
||||
./artifacts/linux-flatpak-aarch64/duckstation-aarch64.flatpak
|
||||
./artifacts/macos/duckstation-mac-release.zip
|
||||
|
||||
- name: Create Rolling Release
|
||||
|
@ -83,6 +91,11 @@ jobs:
|
|||
./artifacts/windows-arm64/duckstation-windows-arm64-release-symbols.zip
|
||||
./artifacts/linux-x64-appimage/DuckStation-x64.AppImage
|
||||
./artifacts/linux-x64-sse2-appimage/DuckStation-x64-SSE2.AppImage
|
||||
./artifacts/linux-flatpak/duckstation-x64.flatpak
|
||||
./artifacts/linux-arm64-appimage/DuckStation-arm64.AppImage
|
||||
./artifacts/linux-arm64-appimage/DuckStation-Mini-arm64.AppImage
|
||||
./artifacts/linux-armhf-appimage/DuckStation-armhf.AppImage
|
||||
./artifacts/linux-armhf-appimage/DuckStation-Mini-armhf.AppImage
|
||||
./artifacts/linux-flatpak-x86_64/duckstation-x86_64.flatpak
|
||||
./artifacts/linux-flatpak-aarch64/duckstation-aarch64.flatpak
|
||||
./artifacts/macos/duckstation-mac-release.zip
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(duckstation C CXX)
|
||||
|
||||
# Policy settings.
|
||||
|
@ -16,10 +16,6 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Debug|Devel|MinSizeRel|RelWithDebInfo|Release")
|
|||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
message(STATUS "CMake Version: ${CMAKE_VERSION}")
|
||||
message(STATUS "CMake System Name: ${CMAKE_SYSTEM_NAME}")
|
||||
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
# Pull in modules.
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules/")
|
||||
include(DuckStationUtils)
|
||||
|
@ -34,6 +30,7 @@ detect_cache_line_size()
|
|||
# Build options. Depends on system attributes.
|
||||
include(DuckStationBuildOptions)
|
||||
include(DuckStationDependencies)
|
||||
include(DuckStationCompilerRequirement)
|
||||
|
||||
# Enable PIC on Linux, otherwise the builds do not support ASLR.
|
||||
if(LINUX OR BSD)
|
||||
|
@ -120,10 +117,6 @@ endif()
|
|||
# Prevent fmt from being built with exceptions, or being thrown at call sites.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFMT_EXCEPTIONS=0")
|
||||
|
||||
# Use C++20.
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Recursively include the source tree.
|
||||
add_subdirectory(dep)
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Renderer options.
|
||||
option(ENABLE_OPENGL "Build with OpenGL renderer" ON)
|
||||
option(ENABLE_VULKAN "Build with Vulkan renderer" ON)
|
||||
option(BUILD_NOGUI_FRONTEND "Build the NoGUI frontend" OFF)
|
||||
option(BUILD_QT_FRONTEND "Build the Qt frontend" ON)
|
||||
option(BUILD_MINI_FRONTEND "Build the Mini frontend" OFF)
|
||||
option(BUILD_REGTEST "Build regression test runner" OFF)
|
||||
option(BUILD_TESTS "Build unit tests" OFF)
|
||||
option(DISABLE_SSE4 "Build with SSE4 instructions disabled, reduces performance" OFF)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if(ENABLE_OPENGL)
|
||||
message(STATUS "Building with OpenGL support.")
|
||||
endif()
|
||||
|
|
16
CMakeModules/DuckStationCompilerRequirement.cmake
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Use C++20.
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# C++20 feature checks. Some Linux environments are incomplete.
|
||||
check_cpp20_feature("__cpp_structured_bindings" 201606)
|
||||
check_cpp20_feature("__cpp_constinit" 201907)
|
||||
check_cpp20_feature("__cpp_designated_initializers" 201707)
|
||||
check_cpp20_feature("__cpp_using_enum" 201907)
|
||||
check_cpp20_feature("__cpp_lib_bit_cast" 201806)
|
||||
check_cpp20_feature("__cpp_lib_bitops" 201907)
|
||||
check_cpp20_feature("__cpp_lib_int_pow2" 202002)
|
||||
check_cpp20_feature("__cpp_lib_starts_ends_with" 201711)
|
||||
check_cpp20_attribute("likely" 201803)
|
||||
check_cpp20_attribute("unlikely" 201803)
|
||||
check_cpp20_attribute("no_unique_address" 201803)
|
|
@ -9,7 +9,7 @@ endif()
|
|||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(SDL2 2.30.8 REQUIRED)
|
||||
find_package(SDL3 3.2.0 REQUIRED)
|
||||
find_package(Zstd 1.5.6 REQUIRED)
|
||||
find_package(WebP REQUIRED) # v1.4.0, spews an error on Linux because no pkg-config.
|
||||
find_package(ZLIB REQUIRED) # 1.3, but Mac currently doesn't use it.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
include(CheckSourceCompiles)
|
||||
|
||||
function(disable_compiler_warnings_for_target target)
|
||||
if(MSVC)
|
||||
target_compile_options(${target} PRIVATE "/W0")
|
||||
|
@ -118,8 +120,11 @@ function(detect_page_size)
|
|||
# For universal Apple builds, we use preprocessor macros to determine page size.
|
||||
# Similar for Windows, except it's always 4KB.
|
||||
if(NOT CPU_ARCH_ARM64 OR NOT LINUX)
|
||||
unset(HOST_PAGE_SIZE CACHE)
|
||||
unset(HOST_PAGE_SIZE PARENT_SCOPE)
|
||||
unset(HOST_MIN_PAGE_SIZE CACHE)
|
||||
unset(HOST_MIN_PAGE_SIZE PARENT_SCOPE)
|
||||
unset(HOST_MAX_PAGE_SIZE CACHE)
|
||||
unset(HOST_MAX_PAGE_SIZE PARENT_SCOPE)
|
||||
return()
|
||||
elseif(DEFINED HOST_PAGE_SIZE)
|
||||
|
@ -166,6 +171,7 @@ endfunction()
|
|||
function(detect_cache_line_size)
|
||||
# This is only needed for ARM64, or if the user hasn't overridden it explicitly.
|
||||
if(NOT CPU_ARCH_ARM64 OR HOST_CACHE_LINE_SIZE)
|
||||
unset(HOST_CACHE_LINE_SIZE CACHE)
|
||||
unset(HOST_CACHE_LINE_SIZE PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
@ -245,3 +251,48 @@ function(install_imported_dep_library name)
|
|||
get_target_property(LOCATION "${name}" IMPORTED_LOCATION_RELEASE)
|
||||
install(FILES "${LOCATION}" RENAME "${SONAME}" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
endfunction()
|
||||
|
||||
function(check_cpp20_feature MACRO MINIMUM_VALUE)
|
||||
set(CACHE_VAR "CHECK_CPP20_FEATURE_${MACRO}")
|
||||
if(NOT DEFINED ${CACHE_VAR})
|
||||
# Create a small source code snippet that fails to compile if the feature is not available.
|
||||
set(TEMP_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cpp")
|
||||
file(WRITE "${TEMP_FILE}" "#include <version>
|
||||
#if !defined(${MACRO}) || ${MACRO} < ${MINIMUM_VALUE}L
|
||||
#error Missing feature
|
||||
#endif
|
||||
")
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
try_compile(HAS_FEATURE
|
||||
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY} "${TEMP_FILE}"
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED TRUE
|
||||
)
|
||||
set(${CACHE_VAR} ${HAS_FEATURE} CACHE INTERNAL "Cached feature test result for ${MACRO}")
|
||||
endif()
|
||||
if(NOT HAS_FEATURE)
|
||||
message(FATAL_ERROR "${MACRO} is not supported by your compiler, at least ${MINIMUM_VALUE} is required.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(check_cpp20_attribute ATTRIBUTE MINIMUM_VALUE)
|
||||
set(CACHE_VAR "CHECK_CPP20_ATTRIBUTE_${MACRO}")
|
||||
if(NOT DEFINED ${CACHE_VAR})
|
||||
set(TEMP_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cpp")
|
||||
file(WRITE "${TEMP_FILE}" "#include <version>
|
||||
#if !defined(__has_cpp_attribute) || __has_cpp_attribute(${ATTRIBUTE}) < ${MINIMUM_VALUE}L
|
||||
#error Missing feature
|
||||
#endif
|
||||
")
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
try_compile(HAS_FEATURE
|
||||
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY} "${TEMP_FILE}"
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED TRUE
|
||||
)
|
||||
set(${CACHE_VAR} ${HAS_FEATURE} CACHE INTERNAL "Cached attribute test result for ${MACRO}")
|
||||
endif()
|
||||
if(NOT HAS_FEATURE)
|
||||
message(FATAL_ERROR "${ATTRIBUTE} is not supported by your compiler, at least ${MINIMUM_VALUE} is required.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
10
README.md
|
@ -23,20 +23,23 @@ DuckStation features a fully-featured frontend built using Qt, as well as a full
|
|||
Other features include:
|
||||
|
||||
- CPU Recompiler/JIT (x86-64, armv7/AArch32, AArch64, RISC-V/RV64).
|
||||
- Hardware (D3D11, D3D12, OpenGL, Vulkan, Metal) and software rendering.
|
||||
- Hardware renderer supporting D3D11, D3D12, OpenGL, Vulkan and Metal APIs.
|
||||
- Upscaling, texture filtering, and true colour (24-bit) in hardware renderers.
|
||||
- Accurate blending via Rasterizer Order Views/Fragment Shader Interlock.
|
||||
- PGXP for geometry precision, texture correction, and depth buffer emulation.
|
||||
- Accurate blending via Rasterizer Order Views/Fragment Shader Interlock.
|
||||
- Texture replacement system in hardware renderers.
|
||||
- Vectorized and multi-threaded software renderer.
|
||||
- Motion adaptive deinterlacing.
|
||||
- Adaptive downsampling filter.
|
||||
- Screen rotation for vertical or "TATE" shmup games.
|
||||
- Post processing shader chains (GLSL and Reshade FX).
|
||||
- Border overlays/bezels displayed around game content.
|
||||
- "Fast boot" for skipping BIOS splash/intro.
|
||||
- Save state support, with runahead and rewind.
|
||||
- Windows, Linux, macOS support.
|
||||
- Supports reading directly from CD, bin/cue images, raw bin/img files, MAME CHD, single-track ECM, MDS/MDF, and unencrypted PBP formats.
|
||||
- Preloading of disc images to RAM to avoid disk sleeping hitches.
|
||||
- Merging of multi-disc games in game list/grid with memory cards shared between discs.
|
||||
- Automatic loading/applying of PPF patches.
|
||||
- Direct booting of homebrew executables.
|
||||
- Direct loading of Portable Sound Format (psf) files.
|
||||
|
@ -44,6 +47,7 @@ Other features include:
|
|||
- Digital and analog controllers for input (rumble is forwarded to host).
|
||||
- GunCon and Justifier lightgun support (simulated with mouse).
|
||||
- NeGcon support.
|
||||
- Controller presets and per-game configuration.
|
||||
- Qt and "Big Picture" UI.
|
||||
- Automatic updates with preview and latest channels.
|
||||
- Automatic content scanning - game titles/hashes are provided by redump.org.
|
||||
|
@ -56,6 +60,8 @@ Other features include:
|
|||
- RetroAchievements.
|
||||
- Discord Rich Presence.
|
||||
- Video capture with Media Foundation (Windows) and [FFmpeg](https://www.ffmpeg.org/) (All Platforms) backends.
|
||||
- Free camera function.
|
||||
- Parallel port cartridge emulation.
|
||||
|
||||
## System Requirements
|
||||
- A CPU faster than a potato. But it needs to be x86_64, AArch32/armv7, AArch64/ARMv8, or RISC-V/RV64.
|
||||
|
|
5422
data/resources/achievement_hashlib.yaml
Normal file
Before Width: | Height: | Size: 39 KiB |
1
data/resources/fullscreenui/back-icon.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ffffff" d="M12 2C17.52 2 22 6.48 22 12C22 17.52 17.52 22 12 22C6.48 22 2 17.52 2 12C2 6.48 6.48 2 12 2ZM12 20C16.42 20 20 16.42 20 12C20 7.58 16.42 4 12 4C7.58 4 4 7.58 4 12C4 16.42 7.58 20 12 20ZM12 11H16V13H12V16L8 12L12 8V11Z"></path></svg>
|
After Width: | Height: | Size: 316 B |
BIN
data/resources/fullscreenui/backgrounds/StaticGray.png
Normal file
After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 34 KiB |
1
data/resources/fullscreenui/desktop-mode.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ffffff" d="M21 3C21.5523 3 22 3.44772 22 4V11H20V5H4V19H10V21H3C2.44772 21 2 20.5523 2 20V4C2 3.44772 2.44772 3 3 3H21ZM21 13C21.5523 13 22 13.4477 22 14V20C22 20.5523 21.5523 21 21 21H13C12.4477 21 12 20.5523 12 20V14C12 13.4477 12.4477 13 13 13H21ZM11.5 7L9.45711 9.04311L11.7071 11.2929L10.2929 12.7071L8.04311 10.4571L6 12.5V7H11.5Z"></path></svg>
|
After Width: | Height: | Size: 424 B |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 58 KiB |
38
data/resources/fullscreenui/exit.svg
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="exit.svg"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="2.640625"
|
||||
inkscape:cx="256"
|
||||
inkscape:cy="256"
|
||||
inkscape:window-width="2856"
|
||||
inkscape:window-height="1651"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="m 363.3838,123.77433 108.17663,108.17663 c 6.3426,6.3426 9.95436,15.06368 9.95436,24.04904 0,8.98535 -3.61176,17.70643 -9.95436,24.04904 L 363.3838,388.22566 c -5.63787,5.63787 -13.21376,8.72108 -21.14202,8.72108 -16.47315,0 -29.86309,-13.38994 -29.86309,-29.86309 V 312.37869 H 199.6213 c -15.59223,0 -28.18935,-12.59711 -28.18935,-28.18935 v -56.37869 c 0,-15.59223 12.59712,-28.18935 28.18935,-28.18935 h 112.75739 v -54.70496 c 0,-16.47315 13.38994,-29.86309 29.86309,-29.86309 7.92826,0 15.50415,3.1713 21.14202,8.72108 z m -191.95185,-8.72108 h -56.3787 c -15.59222,0 -28.189349,12.59712 -28.189349,28.18935 v 225.51479 c 0,15.59223 12.597119,28.18935 28.189349,28.18935 h 56.3787 c 15.59223,0 28.18935,12.59712 28.18935,28.18935 0,15.59223 -12.59712,28.18935 -28.18935,28.18935 h -56.3787 c -46.688603,0 -84.56804,-37.87944 -84.56804,-84.56805 V 143.2426 c 0,-46.688607 37.879437,-84.568041 84.56804,-84.568041 h 56.3787 c 15.59223,0 28.18935,12.597115 28.18935,28.189347 0,15.592224 -12.59712,28.189344 -28.18935,28.189344 z"
|
||||
id="path1"
|
||||
style="stroke-width:0.880917" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 120 KiB |
46
data/resources/fullscreenui/game-list.svg
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 640 640"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="game-list.svg"
|
||||
width="640"
|
||||
height="640"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#000001"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="0.93429246"
|
||||
inkscape:cx="436.69409"
|
||||
inkscape:cy="330.73156"
|
||||
inkscape:window-width="2844"
|
||||
inkscape:window-height="1651"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="m 264.14016,286.21023 c -46.25894,0 -83.78977,37.53084 -83.78977,83.78977 0,46.25893 37.53083,83.78978 83.78977,83.78978 h 111.71968 c 46.25894,0 83.78977,-37.53085 83.78977,-83.78978 0,-46.25894 -37.53083,-83.78977 -83.78977,-83.78977 z m 132.66713,45.38613 a 17.456203,17.456203 0 1 1 0,34.91239 17.456203,17.456203 0 1 1 0,-34.91239 z m -45.38612,59.35108 a 17.456203,17.456203 0 1 1 34.91239,0 17.456203,17.456203 0 1 1 -34.91239,0 z m -97.75473,-45.38612 c 0,-5.80419 4.66954,-10.47373 10.47372,-10.47373 5.80418,0 10.47371,4.66954 10.47371,10.47373 v 13.96496 h 13.96497 c 5.80417,0 10.47373,4.66953 10.47373,10.47372 0,5.80419 -4.66954,10.47372 -10.47373,10.47372 h -13.96497 v 13.96496 c 0,5.80419 -4.66953,10.47373 -10.47371,10.47373 -5.80419,0 -10.47372,-4.66954 -10.47372,-10.47373 v -13.96496 h -13.96496 c -5.8042,0 -10.47373,-4.66953 -10.47373,-10.47372 0,-5.8042 4.66953,-10.47373 10.47373,-10.47373 h 13.96496 z"
|
||||
id="path1"
|
||||
style="stroke-width:0.436405" />
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="m 89.226718,138.67812 c -9.066093,0 -16.483806,7.41772 -16.483806,16.48381 v 329.67613 c 0,9.06609 7.417713,16.4838 16.483806,16.4838 H 550.77329 c 9.06608,0 16.4838,-7.41771 16.4838,-16.4838 V 155.16193 c 0,-9.06609 -7.41772,-16.48381 -16.4838,-16.48381 z m -65.935226,16.48381 c 0,-36.36739 29.567828,-65.935223 65.935226,-65.935223 H 550.77329 c 36.36739,0 65.93522,29.567833 65.93522,65.935223 v 329.67613 c 0,36.36739 -29.56783,65.93523 -65.93522,65.93523 H 89.226718 c -36.367398,0 -65.935226,-29.56784 -65.935226,-65.93523 z m 98.902838,65.93523 c 0,-18.20753 14.76011,-32.96759 32.96761,-32.96759 18.20751,0 32.96761,14.76006 32.96761,32.96759 0,18.20752 -14.7601,32.96759 -32.96761,32.96759 -18.2075,0 -32.96761,-14.76007 -32.96761,-32.96759 z m 107.14475,0 c 0,-13.70217 11.02352,-24.72572 24.72569,-24.72572 h 230.77329 c 13.70216,0 24.72571,11.02355 24.72571,24.72572 0,13.70217 -11.02355,24.72572 -24.72571,24.72572 H 254.06477 c -13.70217,0 -24.72569,-11.02355 -24.72569,-24.72572 z"
|
||||
id="path1-5"
|
||||
style="stroke-width:1.03024"
|
||||
sodipodi:nodetypes="ssssssssssssssssssssssssssssss" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
1
data/resources/fullscreenui/settings.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#ffffff" d="M2.13127 13.6308C1.9492 12.5349 1.95521 11.434 2.13216 10.3695C3.23337 10.3963 4.22374 9.86798 4.60865 8.93871C4.99357 8.00944 4.66685 6.93557 3.86926 6.17581C4.49685 5.29798 5.27105 4.51528 6.17471 3.86911C6.9345 4.66716 8.0087 4.99416 8.93822 4.60914C9.86774 4.22412 10.3961 3.23332 10.369 2.13176C11.4649 1.94969 12.5658 1.9557 13.6303 2.13265C13.6036 3.23385 14.1319 4.22422 15.0612 4.60914C15.9904 4.99406 17.0643 4.66733 17.8241 3.86975C18.7019 4.49734 19.4846 5.27153 20.1308 6.1752C19.3327 6.93499 19.0057 8.00919 19.3907 8.93871C19.7757 9.86823 20.7665 10.3966 21.8681 10.3695C22.0502 11.4654 22.0442 12.5663 21.8672 13.6308C20.766 13.6041 19.7756 14.1324 19.3907 15.0616C19.0058 15.9909 19.3325 17.0648 20.1301 17.8245C19.5025 18.7024 18.7283 19.4851 17.8247 20.1312C17.0649 19.3332 15.9907 19.0062 15.0612 19.3912C14.1316 19.7762 13.6033 20.767 13.6303 21.8686C12.5344 22.0507 11.4335 22.0447 10.3691 21.8677C10.3958 20.7665 9.86749 19.7761 8.93822 19.3912C8.00895 19.0063 6.93508 19.333 6.17532 20.1306C5.29749 19.503 4.51479 18.7288 3.86862 17.8252C4.66667 17.0654 4.99367 15.9912 4.60865 15.0616C4.22363 14.1321 3.23284 13.6038 2.13127 13.6308ZM11.9997 15.0002C13.6565 15.0002 14.9997 13.657 14.9997 12.0002C14.9997 10.3433 13.6565 9.00018 11.9997 9.00018C10.3428 9.00018 8.99969 10.3433 8.99969 12.0002C8.99969 13.657 10.3428 15.0002 11.9997 15.0002Z"></path></svg>
|
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 35 KiB |
38
data/resources/fullscreenui/start-bios.svg
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="start-bios.svg"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="2.640625"
|
||||
inkscape:cx="256"
|
||||
inkscape:cy="256"
|
||||
inkscape:window-width="2852"
|
||||
inkscape:window-height="1651"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="m 186.11835,53.343194 c 0,-11.617826 -9.34668,-20.964498 -20.9645,-20.964498 -11.61782,0 -20.9645,9.346672 -20.9645,20.964498 v 34.940832 c -30.83528,0 -55.905324,25.070044 -55.905324,55.905324 H 53.343194 c -11.617826,0 -20.964498,9.34668 -20.964498,20.9645 0,11.61782 9.346672,20.9645 20.964498,20.9645 H 88.284026 V 235.0355 H 53.343194 c -11.617826,0 -20.964498,9.34668 -20.964498,20.96449 0,11.61783 9.346672,20.96451 20.964498,20.96451 h 34.940832 v 48.91716 H 53.343194 c -11.617826,0 -20.964498,9.34666 -20.964498,20.96449 0,11.61783 9.346672,20.9645 20.964498,20.9645 h 34.940832 c 0,30.83528 25.070044,55.90533 55.905324,55.90533 v 34.94082 c 0,11.61783 9.34668,20.9645 20.9645,20.9645 11.61782,0 20.9645,-9.34667 20.9645,-20.9645 v -34.94082 h 48.91715 v 34.94082 c 0,11.61783 9.34668,20.9645 20.96449,20.9645 11.61783,0 20.96451,-9.34667 20.96451,-20.9645 v -34.94082 h 48.91716 v 34.94082 c 0,11.61783 9.34666,20.9645 20.96449,20.9645 11.61783,0 20.9645,-9.34667 20.9645,-20.9645 v -34.94082 c 30.83528,0 55.90533,-25.07005 55.90533,-55.90533 h 34.94082 c 11.61783,0 20.9645,-9.34667 20.9645,-20.9645 0,-11.61783 -9.34667,-20.96449 -20.9645,-20.96449 H 423.71598 V 276.9645 h 34.94082 c 11.61783,0 20.9645,-9.34668 20.9645,-20.96451 0,-11.61781 -9.34667,-20.96449 -20.9645,-20.96449 h -34.94082 v -48.91715 h 34.94082 c 11.61783,0 20.9645,-9.34668 20.9645,-20.9645 0,-11.61782 -9.34667,-20.9645 -20.9645,-20.9645 h -34.94082 c 0,-30.83528 -25.07005,-55.905324 -55.90533,-55.905324 V 53.343194 c 0,-11.617826 -9.34667,-20.964498 -20.9645,-20.964498 -11.61783,0 -20.96449,9.346672 -20.96449,20.964498 V 88.284026 H 276.9645 V 53.343194 c 0,-11.617826 -9.34668,-20.964498 -20.96451,-20.964498 -11.61781,0 -20.96449,9.346672 -20.96449,20.964498 v 34.940832 h -48.91715 z m -13.97634,90.846156 h 167.71598 c 15.46131,0 27.95266,12.49134 27.95266,27.95266 v 167.71598 c 0,15.46131 -12.49135,27.95266 -27.95266,27.95266 H 172.14201 c -15.46132,0 -27.95266,-12.49135 -27.95266,-27.95266 V 172.14201 c 0,-15.46132 12.49134,-27.95266 27.95266,-27.95266 z m 167.71598,27.95266 H 172.14201 v 167.71598 h 167.71598 z"
|
||||
id="path1"
|
||||
style="stroke-width:0.87352" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 24 KiB |
38
data/resources/fullscreenui/start-disc.svg
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="start-disc.svg"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="1.8685849"
|
||||
inkscape:cx="269.72282"
|
||||
inkscape:cy="294.60797"
|
||||
inkscape:window-width="2856"
|
||||
inkscape:window-height="1652"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="m 49.005172,256 a 206.99483,206.99483 0 1 1 413.989658,0 206.99483,206.99483 0 1 1 -413.989658,0 z M 256,281.87436 a 25.874355,25.874355 0 1 1 0,-51.74871 25.874355,25.874355 0 1 1 0,51.74871 z M 178.37694,256 a 77.62306,77.62306 0 1 0 155.24612,0 77.62306,77.62306 0 1 0 -155.24612,0 z m -51.7487,-12.93717 c 0,-28.30008 14.15003,-57.48958 36.54752,-79.88707 22.39749,-22.39749 51.58699,-36.54752 79.88707,-36.54752 7.11544,0 12.93717,-5.82173 12.93717,-12.93718 0,-7.11545 -5.82173,-12.93718 -12.93717,-12.93718 -36.70924,0 -72.12476,18.03119 -98.24169,44.06726 -26.11692,26.03607 -44.06726,61.53245 -44.06726,98.24169 0,7.11544 5.82173,12.93717 12.93718,12.93717 7.11545,0 12.93718,-5.82173 12.93718,-12.93717 z"
|
||||
id="path1"
|
||||
style="stroke-width:0.808574" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
40
data/resources/fullscreenui/start-file.svg
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 576 576"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="start-file.svg"
|
||||
width="576"
|
||||
height="576"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="2.640625"
|
||||
inkscape:cx="287.81065"
|
||||
inkscape:cy="225.70414"
|
||||
inkscape:window-width="2852"
|
||||
inkscape:window-height="1651"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
|
||||
<path
|
||||
fill="#ffffff"
|
||||
d="m 375.58614,492.32782 h 43.78453 c 10.39883,0 19.97669,-5.47306 25.17611,-14.50363 L 546.71069,302.68606 c 5.29063,-9.03055 5.29063,-20.15913 0.0912,-29.2809 -5.19941,-9.12179 -14.77728,-14.59484 -25.26731,-14.59484 H 156.66347 c -10.39883,0 -19.9767,5.47306 -25.17611,14.50363 L 69.0944,380.22117 V 142.05155 c 0,-8.02715 6.567679,-14.59484 14.594844,-14.59484 H 190.87013 c 3.83116,0 7.57108,1.55071 10.30762,4.28724 l 24.17271,24.17271 c 19.15573,19.15573 45.15279,29.91943 72.24447,29.91943 h 107.1809 c 8.02716,0 14.59484,6.56767 14.59484,14.59484 v 29.1897 h 43.78454 v -29.1897 c 0,-32.19988 -26.17951,-58.37938 -58.37938,-58.37938 h -107.1809 c -15.50702,0 -30.37551,-6.11158 -41.32164,-17.05772 L 232.10058,100.72991 C 221.15444,89.783772 206.28594,83.672181 190.77892,83.672181 H 83.689244 c -32.199876,0 -58.379378,26.179509 -58.379378,58.379369 v 291.89689 c 0,32.19988 26.179502,58.37938 58.379378,58.37938 h 21.618616 z"
|
||||
id="path1"
|
||||
style="stroke-width:0.912178" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -211,7 +211,7 @@
|
|||
03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
|
||||
03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
|
||||
03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
|
||||
03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
|
||||
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
|
||||
03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
|
||||
|
@ -325,7 +325,7 @@
|
|||
030000000d0f0000c100000000000000,Horipad Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,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,
|
||||
030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
|
||||
030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b15,paddle2:b5,paddle3:b19,paddle4:b18,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc2:b2,paddle1:b5,paddle2:b15,paddle3:b18,paddle4:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
|
||||
03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
|
||||
|
@ -638,7 +638,7 @@
|
|||
030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000a30600001af5000000000000,Saitek Cyborg,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,
|
||||
03000000a306000023f6000000000000,Saitek Cyborg V.1 Game,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:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000a306000023f6000000000000,Saitek Cyborg,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:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
|
||||
03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,
|
||||
03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows,
|
||||
|
@ -1051,7 +1051,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,
|
||||
030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,
|
||||
03000000bc2000000155000000010000,SNK NEOGEO Arcade Stick Pro,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b2,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b0,y:b3,platform:Mac OS X,
|
||||
030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
|
||||
03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
|
||||
|
@ -1266,6 +1265,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
@ -1328,6 +1328,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f0000c100000011010000,Horipad Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000000d0f0000ab01000011010000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000000d0f00009601000091000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
|
||||
05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
|
||||
|
@ -1499,8 +1501,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,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,
|
||||
030000006f0e0000d802000006640000,PDP Xbox Series 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,
|
||||
030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired 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,
|
||||
030000006f0e0000f102000000000000,PDP Xbox Atomic,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
03000000c62400000053000000010000,PowerA,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,
|
||||
03000000c62400003a54000001010000,PowerA 1428124-01,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,
|
||||
03000000d62000000540000001010000,PowerA Advantage Xbox Series X 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,
|
||||
03000000d620000011a7000011010000,PowerA Core 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,
|
||||
03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
|
@ -1517,7 +1521,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
|
||||
03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,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,
|
||||
03000000d62000000b20000001010000,PowerA Xbox Series X 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,
|
||||
03000000d62000000540000001010000,PowerA Advantage Xbox Series X 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,
|
||||
030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
|
||||
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
|
@ -1591,6 +1594,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000032150000140a000001010000,Razer Wolverine Ultimate 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,
|
||||
030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f0000c100000072056800,Retro Bit Legacy16,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:+a4,misc1:b11,rightshoulder:b10,righttrigger:+a5,start:b6,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
|
@ -1627,7 +1631,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
|
||||
030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000632500002305000010010000,ShanWan 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,
|
||||
03000000632500002605000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000632500007505000010010000,Shanwan 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,
|
||||
|
@ -1664,6 +1667,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
|||
05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,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,
|
||||
03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,
|
||||
030000001f08000001e4000010010000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
|
||||
0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
|
||||
030000008f0e00000d31000010010000,SZMY Power 3 Turbo,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,
|
||||
|
|
13
data/resources/images/trophy-icon-gray.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 113.48 122.88">
|
||||
<!-- https://uxwing.com/wp-content/themes/uxwing/download/sport-and-awards/trophy-icon.png -->
|
||||
<defs>
|
||||
<style>.cls-1{fill:#808080;}.cls-2{fill:#A0A0A0;}.cls-3{fill:#222;}.cls-4{fill:#C0C0C0;}.cls-5{fill:#909090;}.cls-6{fill:#B0B0B0;}.cls-7,.cls-8{fill:#FFF;}.cls-8{fill-rule:evenodd;}</style>
|
||||
</defs>
|
||||
<title>trophy</title>
|
||||
<path class="cls-1" d="M3.21,18.74H19.86q0-4,.06-8.26V0H93.05V10.49c0,2.92,0,5.66,0,8.26h17.24a3.08,3.08,0,0,1,3.07,2.93,77.67,77.67,0,0,1-.4,13.9A34,34,0,0,1,109.11,48a21.77,21.77,0,0,1-8.8,8.6A31.91,31.91,0,0,1,86.41,60C83.14,65.43,78.78,68,73.68,72.67c-6.17,4.71-10.81,8.26-7.2,19.13h5.39a7.84,7.84,0,0,1,7.82,7.82v3.15h.77A7.69,7.69,0,0,1,85.91,105h0a7.67,7.67,0,0,1,2.26,5.45v5.23a1.77,1.77,0,0,1-1.77,1.77H26.58a1.77,1.77,0,0,1-1.77-1.77v-5.23A7.66,7.66,0,0,1,27.07,105h0a7.66,7.66,0,0,1,5.44-2.26h.77V99.62a7.75,7.75,0,0,1,2.3-5.51v0a7.81,7.81,0,0,1,5.51-2.29h6.06c3.22-10.26-1-13.58-6.83-18.17A44.47,44.47,0,0,1,27.34,60,31.87,31.87,0,0,1,13,56.54a21.47,21.47,0,0,1-8.73-8.6A34.07,34.07,0,0,1,.51,35.58,78.1,78.1,0,0,1,.13,21.9v-.08a3.08,3.08,0,0,1,3.09-3.08ZM92.71,30a121.67,121.67,0,0,1-2,18,15.17,15.17,0,0,0,5-1.9,10.49,10.49,0,0,0,3.69-3.89,18,18,0,0,0,1.93-6,45.37,45.37,0,0,0,.5-6.25H92.71ZM20.12,30H12a49.78,49.78,0,0,0,.45,6.27,18.41,18.41,0,0,0,1.8,6,10.13,10.13,0,0,0,3.57,3.88A14.57,14.57,0,0,0,22.54,48a92,92,0,0,1-2.42-18Z"/>
|
||||
<path class="cls-2" d="M20.08,21.82H3.21C2.75,31.1,3.34,40,7,46.43c3.43,6.11,9.7,10.15,20.62,10.46a27.9,27.9,0,0,1-3.48-5.51c-6.56-.88-10.36-3.59-12.54-7.67S8.94,34.32,8.94,28.14a1.23,1.23,0,0,1,1.23-1.23h9.91V21.82Zm72.77,5.1h10.82a1.23,1.23,0,0,1,1.23,1.22c0,6.2-.56,11.54-2.84,15.6s-6.16,6.75-12.7,7.64a25.38,25.38,0,0,1-3.69,5.52c11-.29,17.29-4.33,20.77-10.45,3.67-6.47,4.29-15.34,3.84-24.62H92.85v5.09Z"/>
|
||||
<path class="cls-3" d="M79.69,102.76h.77A7.69,7.69,0,0,1,85.91,105h0a7.67,7.67,0,0,1,2.26,5.45v10.63a1.77,1.77,0,0,1-1.77,1.77H26.58a1.77,1.77,0,0,1-1.77-1.77V110.48A7.66,7.66,0,0,1,27.07,105h0a7.66,7.66,0,0,1,5.44-2.26H79.69Z"/>
|
||||
<path class="cls-4" d="M70.64,108H35.72a4.22,4.22,0,0,0-3,1.25h0a4.26,4.26,0,0,0-1.25,3v5.28H81.55v-5.28a4.26,4.26,0,0,0-1.26-3,4.31,4.31,0,0,0-3-1.26Z"/>
|
||||
<path class="cls-5" d="M50.71,93h6V75.21c-22.17-7.88-24.26-35-29.55-72.57H22.53V29.41C23,39.6,24.68,47.14,27,52.91a38.19,38.19,0,0,0,8.39,12.8,68.65,68.65,0,0,0,6.71,5.78C49.11,77,54.19,81,50.71,93Z"/>
|
||||
<path class="cls-6" d="M56.71,93H63c-3.88-12.71,1.68-17,9-22.55,8.05-6.14,18.5-14.12,18.5-40.35V2.64H27.16C30.58,26.92,32.66,46.81,39.67,60A39.14,39.14,0,0,0,49,71.13a29.3,29.3,0,0,0,5.47,3.17,19.1,19.1,0,0,0,2.21.74v.15l.07,0V93Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
16
data/resources/images/trophy-icon-star.svg
Normal file
|
@ -0,0 +1,16 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 113.48 122.88">
|
||||
<!-- https://uxwing.com/wp-content/themes/uxwing/download/sport-and-awards/trophy-icon.png -->
|
||||
<defs>
|
||||
<style>.cls-1{fill:#f39d00;}.cls-2{fill:#f9c809;}.cls-3{fill:#222;}.cls-4{fill:#ead79e;}.cls-5{fill:#f8b705;}.cls-6{fill:#fac809;}.cls-7,.cls-8{fill:#fff;}.cls-8{fill-rule:evenodd;}</style>
|
||||
</defs>
|
||||
<title>trophy</title>
|
||||
<path class="cls-1" d="M3.21,18.74H19.86q0-4,.06-8.26V0H93.05V10.49c0,2.92,0,5.66,0,8.26h17.24a3.08,3.08,0,0,1,3.07,2.93,77.67,77.67,0,0,1-.4,13.9A34,34,0,0,1,109.11,48a21.77,21.77,0,0,1-8.8,8.6A31.91,31.91,0,0,1,86.41,60C83.14,65.43,78.78,68,73.68,72.67c-6.17,4.71-10.81,8.26-7.2,19.13h5.39a7.84,7.84,0,0,1,7.82,7.82v3.15h.77A7.69,7.69,0,0,1,85.91,105h0a7.67,7.67,0,0,1,2.26,5.45v5.23a1.77,1.77,0,0,1-1.77,1.77H26.58a1.77,1.77,0,0,1-1.77-1.77v-5.23A7.66,7.66,0,0,1,27.07,105h0a7.66,7.66,0,0,1,5.44-2.26h.77V99.62a7.75,7.75,0,0,1,2.3-5.51v0a7.81,7.81,0,0,1,5.51-2.29h6.06c3.22-10.26-1-13.58-6.83-18.17A44.47,44.47,0,0,1,27.34,60,31.87,31.87,0,0,1,13,56.54a21.47,21.47,0,0,1-8.73-8.6A34.07,34.07,0,0,1,.51,35.58,78.1,78.1,0,0,1,.13,21.9v-.08a3.08,3.08,0,0,1,3.09-3.08ZM92.71,30a121.67,121.67,0,0,1-2,18,15.17,15.17,0,0,0,5-1.9,10.49,10.49,0,0,0,3.69-3.89,18,18,0,0,0,1.93-6,45.37,45.37,0,0,0,.5-6.25H92.71ZM20.12,30H12a49.78,49.78,0,0,0,.45,6.27,18.41,18.41,0,0,0,1.8,6,10.13,10.13,0,0,0,3.57,3.88A14.57,14.57,0,0,0,22.54,48a92,92,0,0,1-2.42-18Z"/>
|
||||
<path class="cls-2" d="M20.08,21.82H3.21C2.75,31.1,3.34,40,7,46.43c3.43,6.11,9.7,10.15,20.62,10.46a27.9,27.9,0,0,1-3.48-5.51c-6.56-.88-10.36-3.59-12.54-7.67S8.94,34.32,8.94,28.14a1.23,1.23,0,0,1,1.23-1.23h9.91V21.82Zm72.77,5.1h10.82a1.23,1.23,0,0,1,1.23,1.22c0,6.2-.56,11.54-2.84,15.6s-6.16,6.75-12.7,7.64a25.38,25.38,0,0,1-3.69,5.52c11-.29,17.29-4.33,20.77-10.45,3.67-6.47,4.29-15.34,3.84-24.62H92.85v5.09Z"/>
|
||||
<path class="cls-3" d="M79.69,102.76h.77A7.69,7.69,0,0,1,85.91,105h0a7.67,7.67,0,0,1,2.26,5.45v10.63a1.77,1.77,0,0,1-1.77,1.77H26.58a1.77,1.77,0,0,1-1.77-1.77V110.48A7.66,7.66,0,0,1,27.07,105h0a7.66,7.66,0,0,1,5.44-2.26H79.69Z"/>
|
||||
<path class="cls-4" d="M70.64,108H35.72a4.22,4.22,0,0,0-3,1.25h0a4.26,4.26,0,0,0-1.25,3v5.28H81.55v-5.28a4.26,4.26,0,0,0-1.26-3,4.31,4.31,0,0,0-3-1.26Z"/>
|
||||
<path class="cls-5" d="M50.71,93h6V75.21c-22.17-7.88-24.26-35-29.55-72.57H22.53V29.41C23,39.6,24.68,47.14,27,52.91a38.19,38.19,0,0,0,8.39,12.8,68.65,68.65,0,0,0,6.71,5.78C49.11,77,54.19,81,50.71,93Z"/>
|
||||
<path class="cls-6" d="M56.71,93H63c-3.88-12.71,1.68-17,9-22.55,8.05-6.14,18.5-14.12,18.5-40.35V2.64H27.16C30.58,26.92,32.66,46.81,39.67,60A39.14,39.14,0,0,0,49,71.13a29.3,29.3,0,0,0,5.47,3.17,19.1,19.1,0,0,0,2.21.74v.15l.07,0V93Z"/>
|
||||
<path class="cls-1" d="M58.26,20.13,61.06,27l7.39.56a1.9,1.9,0,0,1,1,3.41l-5.59,4.74,1.76,7.18a1.9,1.9,0,0,1-1.41,2.29,1.88,1.88,0,0,1-1.49-.26L56.5,41l-6.29,3.89a1.9,1.9,0,0,1-2.62-.62,1.85,1.85,0,0,1-.23-1.44l1.75-7.18-5.66-4.8a1.91,1.91,0,0,1,1.09-3.35L51.93,27l2.81-6.84a1.91,1.91,0,0,1,3.52,0Z"/>
|
||||
<polygon class="cls-7" points="56.5 20.86 59.75 28.78 68.31 29.43 61.76 34.98 63.79 43.3 56.5 38.79 49.21 43.3 51.24 34.98 44.69 29.43 53.24 28.78 56.5 20.86 56.5 20.86 56.5 20.86"/>
|
||||
<path class="cls-8" d="M76.62,47.62l-.07.1a3.79,3.79,0,0,0-5.17.83l-.1-.08a3.52,3.52,0,0,0,.62-2.75,3.57,3.57,0,0,0-1.44-2.42,26.79,26.79,0,0,0,2.82.53,3.58,3.58,0,0,0,2.42-1.45l.1.07a3.81,3.81,0,0,0,.82,5.17ZM84.27,34.8l-.07.1a3.78,3.78,0,0,0-5.17.82l-.1-.07a3.79,3.79,0,0,0-.83-5.17l.07-.1a3.8,3.8,0,0,0,5.18-.83l.09.08a3.79,3.79,0,0,0,.83,5.17Zm.06-13.56-.13.18a6.94,6.94,0,0,0-9.46,1.51l-.18-.13a6.5,6.5,0,0,0,1.14-5,6.49,6.49,0,0,0-2.65-4.43l.13-.18a6.94,6.94,0,0,0,9.46-1.51l.18.13a6.5,6.5,0,0,0-1.14,5,6.51,6.51,0,0,0,2.65,4.43Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
13
data/resources/images/trophy-icon.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 113.48 122.88">
|
||||
<!-- https://uxwing.com/wp-content/themes/uxwing/download/sport-and-awards/trophy-icon.png -->
|
||||
<defs>
|
||||
<style>.cls-1{fill:#f39d00;}.cls-2{fill:#f9c809;}.cls-3{fill:#222;}.cls-4{fill:#ead79e;}.cls-5{fill:#f8b705;}.cls-6{fill:#fac809;}.cls-7,.cls-8{fill:#fff;}.cls-8{fill-rule:evenodd;}</style>
|
||||
</defs>
|
||||
<title>trophy</title>
|
||||
<path class="cls-1" d="M3.21,18.74H19.86q0-4,.06-8.26V0H93.05V10.49c0,2.92,0,5.66,0,8.26h17.24a3.08,3.08,0,0,1,3.07,2.93,77.67,77.67,0,0,1-.4,13.9A34,34,0,0,1,109.11,48a21.77,21.77,0,0,1-8.8,8.6A31.91,31.91,0,0,1,86.41,60C83.14,65.43,78.78,68,73.68,72.67c-6.17,4.71-10.81,8.26-7.2,19.13h5.39a7.84,7.84,0,0,1,7.82,7.82v3.15h.77A7.69,7.69,0,0,1,85.91,105h0a7.67,7.67,0,0,1,2.26,5.45v5.23a1.77,1.77,0,0,1-1.77,1.77H26.58a1.77,1.77,0,0,1-1.77-1.77v-5.23A7.66,7.66,0,0,1,27.07,105h0a7.66,7.66,0,0,1,5.44-2.26h.77V99.62a7.75,7.75,0,0,1,2.3-5.51v0a7.81,7.81,0,0,1,5.51-2.29h6.06c3.22-10.26-1-13.58-6.83-18.17A44.47,44.47,0,0,1,27.34,60,31.87,31.87,0,0,1,13,56.54a21.47,21.47,0,0,1-8.73-8.6A34.07,34.07,0,0,1,.51,35.58,78.1,78.1,0,0,1,.13,21.9v-.08a3.08,3.08,0,0,1,3.09-3.08ZM92.71,30a121.67,121.67,0,0,1-2,18,15.17,15.17,0,0,0,5-1.9,10.49,10.49,0,0,0,3.69-3.89,18,18,0,0,0,1.93-6,45.37,45.37,0,0,0,.5-6.25H92.71ZM20.12,30H12a49.78,49.78,0,0,0,.45,6.27,18.41,18.41,0,0,0,1.8,6,10.13,10.13,0,0,0,3.57,3.88A14.57,14.57,0,0,0,22.54,48a92,92,0,0,1-2.42-18Z"/>
|
||||
<path class="cls-2" d="M20.08,21.82H3.21C2.75,31.1,3.34,40,7,46.43c3.43,6.11,9.7,10.15,20.62,10.46a27.9,27.9,0,0,1-3.48-5.51c-6.56-.88-10.36-3.59-12.54-7.67S8.94,34.32,8.94,28.14a1.23,1.23,0,0,1,1.23-1.23h9.91V21.82Zm72.77,5.1h10.82a1.23,1.23,0,0,1,1.23,1.22c0,6.2-.56,11.54-2.84,15.6s-6.16,6.75-12.7,7.64a25.38,25.38,0,0,1-3.69,5.52c11-.29,17.29-4.33,20.77-10.45,3.67-6.47,4.29-15.34,3.84-24.62H92.85v5.09Z"/>
|
||||
<path class="cls-3" d="M79.69,102.76h.77A7.69,7.69,0,0,1,85.91,105h0a7.67,7.67,0,0,1,2.26,5.45v10.63a1.77,1.77,0,0,1-1.77,1.77H26.58a1.77,1.77,0,0,1-1.77-1.77V110.48A7.66,7.66,0,0,1,27.07,105h0a7.66,7.66,0,0,1,5.44-2.26H79.69Z"/>
|
||||
<path class="cls-4" d="M70.64,108H35.72a4.22,4.22,0,0,0-3,1.25h0a4.26,4.26,0,0,0-1.25,3v5.28H81.55v-5.28a4.26,4.26,0,0,0-1.26-3,4.31,4.31,0,0,0-3-1.26Z"/>
|
||||
<path class="cls-5" d="M50.71,93h6V75.21c-22.17-7.88-24.26-35-29.55-72.57H22.53V29.41C23,39.6,24.68,47.14,27,52.91a38.19,38.19,0,0,0,8.39,12.8,68.65,68.65,0,0,0,6.71,5.78C49.11,77,54.19,81,50.71,93Z"/>
|
||||
<path class="cls-6" d="M56.71,93H63c-3.88-12.71,1.68-17,9-22.55,8.05-6.14,18.5-14.12,18.5-40.35V2.64H27.16C30.58,26.92,32.66,46.81,39.67,60A39.14,39.14,0,0,0,49,71.13a29.3,29.3,0,0,0,5.47,3.17,19.1,19.1,0,0,0,2.21.74v.15l.07,0V93Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
11
data/resources/overlays/OVERLAY_CREDITS_AND_LICENSE.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Psx.jpg Credits
|
||||
|
||||
To the Author: SOQUEROEU.
|
||||
|
||||
The "psx.jpg" background was edited from the one obtained from "Soqueroeu TV Backgrounds 2.0" repository: https://github.com/soqueroeu/Soqueroeu-TV-Backgrounds_V2.0/tree/main.
|
||||
|
||||
The material is free to use according to the agreement below:
|
||||
|
||||
## AGREEMENT
|
||||
|
||||
This pack is free. You should not pay for anything related to this graphics pack and shader preset. You may distribute and reproduce part from this content, as long as you give credit to the authors involved. You may not profit from the sale of products that contain material in this package without the author's prior permission.
|
BIN
data/resources/overlays/psx.webp
Normal file
After Width: | Height: | Size: 263 KiB |
7
data/resources/overlays/psx.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
image: "psx.webp"
|
||||
displayStartX: 990
|
||||
displayStartY: 260
|
||||
displayEndX: 2850
|
||||
displayEndY: 1655
|
||||
alphaBlend: false
|
||||
destinationAlphaBlend: false
|
|
@ -1,2 +0,0 @@
|
|||
lbsubmit.wav: https://freesound.org/people/Eponn/sounds/636656/
|
||||
unlock.wav and message.wav are from https://github.com/RetroAchievements/RAInterface
|
3
data/resources/sounds/achievements/sources.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
lbsubmit.wav: https://pixabay.com/sound-effects/notification-sound-7062/
|
||||
unlock.wav: https://pixabay.com/sound-effects/notification-pluck-on-269288/
|
||||
message.wav: https://pixabay.com/sound-effects/system-notification-199277/
|
|
@ -1,3 +1,6 @@
|
|||
set(_saved_CMAKE_MESSAGE_LOG_LEVEL ${CMAKE_MESSAGE_LOG_LEVEL})
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL NOTICE)
|
||||
|
||||
set(FMT_INSTALL OFF CACHE BOOL "")
|
||||
add_subdirectory(fmt EXCLUDE_FROM_ALL)
|
||||
disable_compiler_warnings_for_target(fmt)
|
||||
|
@ -55,3 +58,4 @@ if(WIN32)
|
|||
add_subdirectory(winpixeventruntime EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL ${_saved_CMAKE_MESSAGE_LOG_LEVEL})
|
||||
|
|
|
@ -6,3 +6,9 @@ IndentPPDirectives: AfterHash
|
|||
IndentCaseLabels: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
DerivePointerAlignment: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCaseColons: false
|
|
@ -27,7 +27,13 @@ endfunction()
|
|||
# DEPRECATED! Should be merged into add_module_library.
|
||||
function(enable_module target)
|
||||
if (MSVC)
|
||||
set(BMI ${CMAKE_CURRENT_BINARY_DIR}/${target}.ifc)
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
# Ninja dyndep expects the .ifc output to be located in a specific relative path
|
||||
file(RELATIVE_PATH BMI_DIR "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${target}.dir")
|
||||
else()
|
||||
set(BMI_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
file(TO_NATIVE_PATH "${BMI_DIR}/${target}.ifc" BMI)
|
||||
target_compile_options(${target}
|
||||
PRIVATE /interface /ifcOutput ${BMI}
|
||||
INTERFACE /reference fmt=${BMI})
|
||||
|
@ -69,8 +75,6 @@ function(add_module_library name)
|
|||
target_compile_options(${name} PUBLIC -fmodules-ts)
|
||||
endif ()
|
||||
|
||||
target_compile_definitions(${name} PRIVATE FMT_MODULE)
|
||||
|
||||
if (FMT_USE_CMAKE_MODULES)
|
||||
target_sources(${name} PUBLIC FILE_SET fmt TYPE CXX_MODULES
|
||||
FILES ${sources})
|
||||
|
@ -240,7 +244,13 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
|||
endif ()
|
||||
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wshift-overflow=2
|
||||
-Wnull-dereference -Wduplicated-cond)
|
||||
-Wduplicated-cond)
|
||||
# Workaround for GCC regression
|
||||
# [12/13/14/15 regression] New (since gcc 12) false positive null-dereference in vector.resize
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108860
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
||||
set(PEDANTIC_COMPILE_FLAGS ${PEDANTIC_COMPILE_FLAGS} -Wnull-dereference)
|
||||
endif ()
|
||||
endif ()
|
||||
set(WERROR_FLAG -Werror)
|
||||
endif ()
|
||||
|
@ -289,6 +299,7 @@ function(add_headers VAR)
|
|||
endfunction()
|
||||
|
||||
# Define the fmt library, its includes and the needed defines.
|
||||
set(FMT_HEADERS)
|
||||
add_headers(FMT_HEADERS args.h base.h chrono.h color.h compile.h core.h format.h
|
||||
format-inl.h os.h ostream.h printf.h ranges.h std.h
|
||||
xchar.h)
|
||||
|
@ -319,7 +330,7 @@ else ()
|
|||
message(WARNING "Feature cxx_std_11 is unknown for the CXX compiler")
|
||||
endif ()
|
||||
|
||||
target_include_directories(fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
|
||||
target_include_directories(fmt ${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)
|
||||
|
||||
|
@ -359,8 +370,8 @@ if (NOT MSVC)
|
|||
# Unicode is always supported on compilers other than MSVC.
|
||||
elseif (FMT_UNICODE)
|
||||
# Unicode support requires compiling with /utf-8.
|
||||
target_compile_options(fmt PUBLIC $<$<COMPILE_LANGUAGE:CXX>:/utf-8>)
|
||||
target_compile_options(fmt-header-only INTERFACE $<$<COMPILE_LANGUAGE:CXX>:/utf-8>)
|
||||
target_compile_options(fmt PUBLIC $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
|
||||
target_compile_options(fmt-header-only INTERFACE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)
|
||||
else ()
|
||||
target_compile_definitions(fmt PUBLIC FMT_UNICODE=0)
|
||||
endif ()
|
||||
|
@ -369,7 +380,7 @@ target_compile_definitions(fmt-header-only INTERFACE FMT_HEADER_ONLY=1)
|
|||
target_compile_features(fmt-header-only INTERFACE cxx_std_11)
|
||||
|
||||
target_include_directories(fmt-header-only
|
||||
${FMT_SYSTEM_HEADERS_ATTRIBUTE} INTERFACE
|
||||
${FMT_SYSTEM_HEADERS_ATTRIBUTE} BEFORE INTERFACE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${FMT_INC_DIR}>)
|
||||
|
||||
|
@ -420,7 +431,9 @@ if (FMT_INSTALL)
|
|||
endif()
|
||||
|
||||
# Install the library and headers.
|
||||
install(TARGETS ${INSTALL_TARGETS} EXPORT ${targets_export_name}
|
||||
install(TARGETS ${INSTALL_TARGETS}
|
||||
COMPONENT fmt-core
|
||||
EXPORT ${targets_export_name}
|
||||
LIBRARY DESTINATION ${FMT_LIB_DIR}
|
||||
ARCHIVE DESTINATION ${FMT_LIB_DIR}
|
||||
PUBLIC_HEADER DESTINATION "${FMT_INC_DIR}/fmt"
|
||||
|
@ -433,13 +446,15 @@ if (FMT_INSTALL)
|
|||
FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake)
|
||||
|
||||
# Install version, config and target files.
|
||||
install(
|
||||
FILES ${project_config} ${version_config}
|
||||
DESTINATION ${FMT_CMAKE_DIR})
|
||||
install(FILES ${project_config} ${version_config}
|
||||
DESTINATION ${FMT_CMAKE_DIR}
|
||||
COMPONENT fmt-core)
|
||||
install(EXPORT ${targets_export_name} DESTINATION ${FMT_CMAKE_DIR}
|
||||
NAMESPACE fmt::)
|
||||
NAMESPACE fmt::
|
||||
COMPONENT fmt-core)
|
||||
|
||||
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}")
|
||||
install(FILES "${pkgconfig}" DESTINATION "${FMT_PKGCONFIG_DIR}"
|
||||
COMPONENT fmt-core)
|
||||
endif ()
|
||||
|
||||
function(add_doc_target)
|
||||
|
@ -475,7 +490,8 @@ function(add_doc_target)
|
|||
|
||||
include(GNUInstallDirs)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc-html/
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt OPTIONAL)
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/fmt
|
||||
COMPONENT fmt-doc OPTIONAL)
|
||||
endfunction()
|
||||
|
||||
if (FMT_DOC)
|
||||
|
|
|
@ -1,3 +1,322 @@
|
|||
# 11.1.4 - 2025-02-26
|
||||
|
||||
- Fixed ABI compatibility with earlier 11.x versions on Windows
|
||||
(https://github.com/fmtlib/fmt/issues/4359).
|
||||
|
||||
- Improved the logic of switching between fixed and exponential format for
|
||||
`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.
|
||||
|
||||
- Simplified implementation of `operator""_cf`
|
||||
(https://github.com/fmtlib/fmt/pull/4349). Thanks @LocalSpook.
|
||||
|
||||
- Fixed `__builtin_strlen` detection (https://github.com/fmtlib/fmt/pull/4329).
|
||||
Thanks @LocalSpook.
|
||||
|
||||
- Fixed handling of BMI paths with the Ninja generator
|
||||
(https://github.com/fmtlib/fmt/pull/4344). Thanks @tkhyn.
|
||||
|
||||
- Fixed gcc 8.3 compile errors (https://github.com/fmtlib/fmt/issues/4331,
|
||||
https://github.com/fmtlib/fmt/pull/4336). Thanks @sergiud.
|
||||
|
||||
- Fixed a bogus MSVC warning (https://github.com/fmtlib/fmt/pull/4356).
|
||||
Thanks @dinomight.
|
||||
|
||||
# 11.1.3 - 2025-01-25
|
||||
|
||||
- Fixed compilation on GCC 9.4 (https://github.com/fmtlib/fmt/issues/4313).
|
||||
|
||||
- Worked around an internal compiler error when using C++20 modules with GCC
|
||||
14.2 and earlier (https://github.com/fmtlib/fmt/issues/4295).
|
||||
|
||||
- Worked around a bug in GCC 6 (https://github.com/fmtlib/fmt/issues/4318).
|
||||
|
||||
- Fixed an issue caused by instantiating `formatter<const T>`
|
||||
(https://github.com/fmtlib/fmt/issues/4303,
|
||||
https://github.com/fmtlib/fmt/pull/4325). Thanks @timsong-cpp.
|
||||
|
||||
- Fixed formatting into `std::ostreambuf_iterator` when using format string
|
||||
compilation (https://github.com/fmtlib/fmt/issues/4309,
|
||||
https://github.com/fmtlib/fmt/pull/4312). Thanks @phprus.
|
||||
|
||||
- Restored a constraint on the map formatter so that it correctly reports as
|
||||
unformattable when the element is (https://github.com/fmtlib/fmt/pull/4326).
|
||||
Thanks @timsong-cpp.
|
||||
|
||||
- Reduced the size of format specs (https://github.com/fmtlib/fmt/issues/4298).
|
||||
|
||||
- Readded `args()` to `fmt::format_context`
|
||||
(https://github.com/fmtlib/fmt/issues/4307,
|
||||
https://github.com/fmtlib/fmt/pull/4310). Thanks @Erroneous1.
|
||||
|
||||
- Fixed a bogus MSVC warning (https://github.com/fmtlib/fmt/issues/4314,
|
||||
https://github.com/fmtlib/fmt/pull/4322). Thanks @ZehMatt.
|
||||
|
||||
- Fixed a pedantic mode error in the CMake config
|
||||
(https://github.com/fmtlib/fmt/pull/4327). Thanks @rlalik.
|
||||
|
||||
# 11.1.2 - 2025-01-12
|
||||
|
||||
- Fixed ABI compatibility with earlier 11.x versions
|
||||
(https://github.com/fmtlib/fmt/issues/4292).
|
||||
|
||||
- Added `wchar_t` support to the `std::bitset` formatter
|
||||
(https://github.com/fmtlib/fmt/issues/4285,
|
||||
https://github.com/fmtlib/fmt/pull/4286,
|
||||
https://github.com/fmtlib/fmt/issues/4289,
|
||||
https://github.com/fmtlib/fmt/pull/4290). Thanks @phprus.
|
||||
|
||||
- Prefixed CMake components with `fmt-` to simplify usage of {fmt} via
|
||||
`add_subdirectory` (https://github.com/fmtlib/fmt/issues/4283).
|
||||
|
||||
- Updated docs for meson (https://github.com/fmtlib/fmt/pull/4291).
|
||||
Thanks @trim21.
|
||||
|
||||
- Fixed a compilation error in chrono on nvcc
|
||||
(https://github.com/fmtlib/fmt/issues/4297,
|
||||
https://github.com/fmtlib/fmt/pull/4301). Thanks @breyerml.
|
||||
|
||||
- Fixed various warnings
|
||||
(https://github.com/fmtlib/fmt/pull/4288,
|
||||
https://github.com/fmtlib/fmt/pull/4299). Thanks @GamesTrap and @edo9300.
|
||||
|
||||
# 11.1.1 - 2024-12-27
|
||||
|
||||
- Fixed ABI compatibility with earlier 11.x versions
|
||||
(https://github.com/fmtlib/fmt/issues/4278).
|
||||
|
||||
- Defined CMake components (`core` and `doc`) to allow docs to be installed
|
||||
separately (https://github.com/fmtlib/fmt/pull/4276).
|
||||
Thanks @carlsmedstad.
|
||||
|
||||
# 11.1.0 - 2024-12-25
|
||||
|
||||
- Improved C++20 module support
|
||||
(https://github.com/fmtlib/fmt/issues/4081,
|
||||
https://github.com/fmtlib/fmt/pull/4083,
|
||||
https://github.com/fmtlib/fmt/pull/4084,
|
||||
https://github.com/fmtlib/fmt/pull/4152,
|
||||
https://github.com/fmtlib/fmt/issues/4153,
|
||||
https://github.com/fmtlib/fmt/pull/4169,
|
||||
https://github.com/fmtlib/fmt/issues/4190,
|
||||
https://github.com/fmtlib/fmt/issues/4234,
|
||||
https://github.com/fmtlib/fmt/pull/4239).
|
||||
Thanks @kamrann and @Arghnews.
|
||||
|
||||
- Reduced debug (unoptimized) binary code size and the number of template
|
||||
instantiations when passing formatting arguments. For example, unoptimized
|
||||
binary code size for `fmt::print("{}", 42)` was reduced by ~40% on GCC and
|
||||
~60% on clang (x86-64).
|
||||
|
||||
GCC:
|
||||
- Before: 161 instructions of which 105 are in reusable functions
|
||||
([godbolt](https://www.godbolt.org/z/s9bGoo4ze)).
|
||||
- After: 116 instructions of which 60 are in reusable functions
|
||||
([godbolt](https://www.godbolt.org/z/r7GGGxMs6)).
|
||||
|
||||
Clang:
|
||||
- Before: 310 instructions of which 251 are in reusable functions
|
||||
([godbolt](https://www.godbolt.org/z/Ts88b7M9o)).
|
||||
- After: 194 instructions of which 135 are in reusable functions
|
||||
([godbolt](https://www.godbolt.org/z/vcrjP8ceW)).
|
||||
|
||||
- Added an experimental `fmt::writer` API that can be used for writing to
|
||||
different destinations such as files or strings
|
||||
(https://github.com/fmtlib/fmt/issues/2354).
|
||||
For example ([godbolt](https://www.godbolt.org/z/rWoKfbP7e)):
|
||||
|
||||
```c++
|
||||
#include <fmt/os.h>
|
||||
|
||||
void write_text(fmt::writer w) {
|
||||
w.print("The answer is {}.", 42);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Write to FILE.
|
||||
write_text(stdout);
|
||||
|
||||
// Write to fmt::ostream.
|
||||
auto f = fmt::output_file("myfile");
|
||||
write_text(f);
|
||||
|
||||
// Write to std::string.
|
||||
auto sb = fmt::string_buffer();
|
||||
write_text(sb);
|
||||
std::string s = sb.str();
|
||||
}
|
||||
```
|
||||
|
||||
- Added width and alignment support to the formatter of `std::error_code`.
|
||||
|
||||
- Made `std::expected<void, E>` formattable
|
||||
(https://github.com/fmtlib/fmt/issues/4145,
|
||||
https://github.com/fmtlib/fmt/pull/4148).
|
||||
For example ([godbolt](https://www.godbolt.org/z/hrj5c6G86)):
|
||||
|
||||
```c++
|
||||
fmt::print("{}", std::expected<void, int>());
|
||||
```
|
||||
|
||||
prints
|
||||
|
||||
```
|
||||
expected()
|
||||
```
|
||||
|
||||
Thanks @phprus.
|
||||
|
||||
- Made `fmt::is_formattable<void>` SFINAE-friendly
|
||||
(https://github.com/fmtlib/fmt/issues/4147).
|
||||
|
||||
- Added support for `_BitInt` formatting when using clang
|
||||
(https://github.com/fmtlib/fmt/issues/4007,
|
||||
https://github.com/fmtlib/fmt/pull/4072,
|
||||
https://github.com/fmtlib/fmt/issues/4140,
|
||||
https://github.com/fmtlib/fmt/issues/4173,
|
||||
https://github.com/fmtlib/fmt/pull/4176).
|
||||
For example ([godbolt](https://www.godbolt.org/z/KWjbWec5z)):
|
||||
|
||||
```c++
|
||||
using int42 = _BitInt(42);
|
||||
fmt::print("{}", int42(100));
|
||||
```
|
||||
|
||||
Thanks @Arghnews.
|
||||
|
||||
- Added the `n` specifier for tuples and pairs
|
||||
(https://github.com/fmtlib/fmt/pull/4107). Thanks @someonewithpc.
|
||||
|
||||
- Added support for tuple-like types to `fmt::join`
|
||||
(https://github.com/fmtlib/fmt/issues/4226,
|
||||
https://github.com/fmtlib/fmt/pull/4230). Thanks @phprus.
|
||||
|
||||
- Made more types formattable at compile time
|
||||
(https://github.com/fmtlib/fmt/pull/4127). Thanks @AnthonyVH.
|
||||
|
||||
- Implemented a more efficient compile-time `fmt::formatted_size`
|
||||
(https://github.com/fmtlib/fmt/issues/4102,
|
||||
https://github.com/fmtlib/fmt/pull/4103). Thanks @phprus.
|
||||
|
||||
- Fixed compile-time formatting of some string types
|
||||
(https://github.com/fmtlib/fmt/pull/4065). Thanks @torshepherd.
|
||||
|
||||
- Made compiled version of `fmt::format_to` work with
|
||||
`std::back_insert_iterator<std::vector<char>>`
|
||||
(https://github.com/fmtlib/fmt/issues/4206,
|
||||
https://github.com/fmtlib/fmt/pull/4211). Thanks @phprus.
|
||||
|
||||
- Added a formatter for `std::reference_wrapper`
|
||||
(https://github.com/fmtlib/fmt/pull/4163,
|
||||
https://github.com/fmtlib/fmt/pull/4164). Thanks @yfeldblum and @phprus.
|
||||
|
||||
- Added experimental padding support (glibc `strftime` extension) to `%m`, `%j`
|
||||
and `%Y` (https://github.com/fmtlib/fmt/pull/4161). Thanks @KKhanhH.
|
||||
|
||||
- Made microseconds formatted as `us` instead of `µs` if the Unicode support is
|
||||
disabled (https://github.com/fmtlib/fmt/issues/4088).
|
||||
|
||||
- Fixed an unreleased regression in transcoding of surrogate pairs
|
||||
(https://github.com/fmtlib/fmt/issues/4094,
|
||||
https://github.com/fmtlib/fmt/pull/4095). Thanks @phprus.
|
||||
|
||||
- Made `fmt::appender` satisfy `std::output_iterator` concept
|
||||
(https://github.com/fmtlib/fmt/issues/4092,
|
||||
https://github.com/fmtlib/fmt/pull/4093). Thanks @phprus.
|
||||
|
||||
- Made `std::iterator_traits<fmt::appender>` standard-conforming
|
||||
(https://github.com/fmtlib/fmt/pull/4185). Thanks @CaseyCarter.
|
||||
|
||||
- Made it easier to reuse `fmt::formatter<std::string_view>` for types with
|
||||
an implicit conversion to `std::string_view`
|
||||
(https://github.com/fmtlib/fmt/issues/4036,
|
||||
https://github.com/fmtlib/fmt/pull/4055). Thanks @Arghnews.
|
||||
|
||||
- Made it possible to disable `<filesystem>` use via `FMT_CPP_LIB_FILESYSTEM`
|
||||
for compatibility with some video game console SDKs, e.g. Nintendo Switch SDK
|
||||
(https://github.com/fmtlib/fmt/issues/4257,
|
||||
https://github.com/fmtlib/fmt/pull/4258,
|
||||
https://github.com/fmtlib/fmt/pull/4259). Thanks @W4RH4WK and @phprus.
|
||||
|
||||
- Fixed compatibility with platforms that use 80-bit `long double`
|
||||
(https://github.com/fmtlib/fmt/issues/4245,
|
||||
https://github.com/fmtlib/fmt/pull/4246). Thanks @jsirpoma.
|
||||
|
||||
- Added support for UTF-32 code units greater than `0xFFFF` in fill
|
||||
(https://github.com/fmtlib/fmt/issues/4201).
|
||||
|
||||
- Fixed handling of legacy encodings on Windows with GCC
|
||||
(https://github.com/fmtlib/fmt/issues/4162).
|
||||
|
||||
- Made `fmt::to_string` take `fmt::basic_memory_buffer` by const reference
|
||||
(https://github.com/fmtlib/fmt/issues/4261,
|
||||
https://github.com/fmtlib/fmt/pull/4262). Thanks @sascha-devel.
|
||||
|
||||
- Added `fmt::dynamic_format_arg_store::size`
|
||||
(https://github.com/fmtlib/fmt/pull/4270). Thanks @hannes-harnisch.
|
||||
|
||||
- Removed the ability to control locale usage via an undocumented
|
||||
`FMT_STATIC_THOUSANDS_SEPARATOR` in favor of `FMT_USE_LOCALE`.
|
||||
|
||||
- Renamed `FMT_EXCEPTIONS` to `FMT_USE_EXCEPTIONS` for consistency with other
|
||||
similar macros.
|
||||
|
||||
- Improved include directory ordering to reduce the chance of including
|
||||
incorrect headers when using multiple versions of {fmt}
|
||||
(https://github.com/fmtlib/fmt/pull/4116). Thanks @cdzhan.
|
||||
|
||||
- Made it possible to compile a subset of {fmt} without the C++ runtime.
|
||||
|
||||
- Improved documentation and README
|
||||
(https://github.com/fmtlib/fmt/pull/4066,
|
||||
https://github.com/fmtlib/fmt/issues/4117,
|
||||
https://github.com/fmtlib/fmt/issues/4203,
|
||||
https://github.com/fmtlib/fmt/pull/4235). Thanks @zyctree and @nikola-sh.
|
||||
|
||||
- Improved the documentation generator (https://github.com/fmtlib/fmt/pull/4110,
|
||||
https://github.com/fmtlib/fmt/pull/4115). Thanks @rturrado.
|
||||
|
||||
- Improved CI (https://github.com/fmtlib/fmt/pull/4155,
|
||||
https://github.com/fmtlib/fmt/pull/4151). Thanks @phprus.
|
||||
|
||||
- Fixed various warnings and compilation issues
|
||||
(https://github.com/fmtlib/fmt/issues/2708,
|
||||
https://github.com/fmtlib/fmt/issues/4091,
|
||||
https://github.com/fmtlib/fmt/issues/4109,
|
||||
https://github.com/fmtlib/fmt/issues/4113,
|
||||
https://github.com/fmtlib/fmt/issues/4125,
|
||||
https://github.com/fmtlib/fmt/issues/4129,
|
||||
https://github.com/fmtlib/fmt/pull/4130,
|
||||
https://github.com/fmtlib/fmt/pull/4131,
|
||||
https://github.com/fmtlib/fmt/pull/4132,
|
||||
https://github.com/fmtlib/fmt/issues/4133,
|
||||
https://github.com/fmtlib/fmt/issues/4144,
|
||||
https://github.com/fmtlib/fmt/issues/4150,
|
||||
https://github.com/fmtlib/fmt/issues/4158,
|
||||
https://github.com/fmtlib/fmt/pull/4159,
|
||||
https://github.com/fmtlib/fmt/issues/4160,
|
||||
https://github.com/fmtlib/fmt/pull/4170,
|
||||
https://github.com/fmtlib/fmt/issues/4177,
|
||||
https://github.com/fmtlib/fmt/pull/4187,
|
||||
https://github.com/fmtlib/fmt/pull/4188,
|
||||
https://github.com/fmtlib/fmt/pull/4194,
|
||||
https://github.com/fmtlib/fmt/pull/4200,
|
||||
https://github.com/fmtlib/fmt/issues/4205,
|
||||
https://github.com/fmtlib/fmt/issues/4207,
|
||||
https://github.com/fmtlib/fmt/pull/4208,
|
||||
https://github.com/fmtlib/fmt/pull/4210,
|
||||
https://github.com/fmtlib/fmt/issues/4220,
|
||||
https://github.com/fmtlib/fmt/issues/4231,
|
||||
https://github.com/fmtlib/fmt/issues/4232,
|
||||
https://github.com/fmtlib/fmt/pull/4233,
|
||||
https://github.com/fmtlib/fmt/pull/4236,
|
||||
https://github.com/fmtlib/fmt/pull/4267,
|
||||
https://github.com/fmtlib/fmt/pull/4271).
|
||||
Thanks @torsten48, @Arghnews, @tinfoilboy, @aminya, @Ottani, @zeroomega,
|
||||
@c4v4, @kongy, @vinayyadav3016, @sergio-nsk, @phprus and @YexuanXiao.
|
||||
|
||||
# 11.0.2 - 2024-07-20
|
||||
|
||||
- Fixed compatibility with non-POSIX systems
|
||||
|
@ -268,6 +587,9 @@
|
|||
- Fixed handling of negative ids in `fmt::basic_format_args::get`
|
||||
(https://github.com/fmtlib/fmt/pull/3945). Thanks @marlenecota.
|
||||
|
||||
- Fixed handling of a buffer boundary on flush
|
||||
(https://github.com/fmtlib/fmt/issues/4229).
|
||||
|
||||
- Improved named argument validation
|
||||
(https://github.com/fmtlib/fmt/issues/3817).
|
||||
|
||||
|
|
|
@ -291,6 +291,7 @@ converts to `std::print`.)
|
|||
- [ccache](https://ccache.dev/): a compiler cache
|
||||
- [ClickHouse](https://github.com/ClickHouse/ClickHouse): an
|
||||
analytical database management system
|
||||
- [ContextVision](https://www.contextvision.com/): medical imaging software
|
||||
- [Contour](https://github.com/contour-terminal/contour/): a modern
|
||||
terminal emulator
|
||||
- [CUAUV](https://cuauv.org/): Cornell University\'s autonomous
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "format.h" // std_string_view
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T> struct is_reference_wrapper : std::false_type {};
|
||||
|
@ -72,19 +71,13 @@ 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
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
// Workaround a GCC template argument substitution bug.
|
||||
: public basic_format_args<Context>
|
||||
#endif
|
||||
{
|
||||
template <typename Context> class dynamic_format_arg_store {
|
||||
private:
|
||||
using char_type = typename Context::char_type;
|
||||
|
||||
template <typename T> struct need_copy {
|
||||
static constexpr detail::type mapped_type =
|
||||
detail::mapped_type_constant<T, Context>::value;
|
||||
detail::mapped_type_constant<T, char_type>::value;
|
||||
|
||||
enum {
|
||||
value = !(detail::is_reference_wrapper<T>::value ||
|
||||
|
@ -97,7 +90,7 @@ class dynamic_format_arg_store
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
using stored_type = conditional_t<
|
||||
using stored_t = conditional_t<
|
||||
std::is_convertible<T, std::basic_string<char_type>>::value &&
|
||||
!detail::is_reference_wrapper<T>::value,
|
||||
std::basic_string<char_type>, T>;
|
||||
|
@ -112,41 +105,37 @@ class dynamic_format_arg_store
|
|||
|
||||
friend class basic_format_args<Context>;
|
||||
|
||||
auto get_types() const -> unsigned long long {
|
||||
return detail::is_unpacked_bit | data_.size() |
|
||||
(named_info_.empty()
|
||||
? 0ULL
|
||||
: static_cast<unsigned long long>(detail::has_named_args_bit));
|
||||
}
|
||||
|
||||
auto data() const -> const basic_format_arg<Context>* {
|
||||
return named_info_.empty() ? data_.data() : data_.data() + 1;
|
||||
}
|
||||
|
||||
template <typename T> void emplace_arg(const T& arg) {
|
||||
data_.emplace_back(detail::make_arg<Context>(arg));
|
||||
data_.emplace_back(arg);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void emplace_arg(const detail::named_arg<char_type, T>& arg) {
|
||||
if (named_info_.empty()) {
|
||||
constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr};
|
||||
data_.insert(data_.begin(), {zero_ptr, 0});
|
||||
}
|
||||
data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value)));
|
||||
if (named_info_.empty())
|
||||
data_.insert(data_.begin(), basic_format_arg<Context>(nullptr, 0));
|
||||
data_.emplace_back(detail::unwrap(arg.value));
|
||||
auto pop_one = [](std::vector<basic_format_arg<Context>>* data) {
|
||||
data->pop_back();
|
||||
};
|
||||
std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)>
|
||||
guard{&data_, pop_one};
|
||||
named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)});
|
||||
data_[0].value_.named_args = {named_info_.data(), named_info_.size()};
|
||||
data_[0] = {named_info_.data(), named_info_.size()};
|
||||
guard.release();
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr dynamic_format_arg_store() = default;
|
||||
|
||||
operator basic_format_args<Context>() const {
|
||||
return basic_format_args<Context>(data(), static_cast<int>(data_.size()),
|
||||
!named_info_.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an argument into the dynamic store for later passing to a formatting
|
||||
* function.
|
||||
|
@ -164,7 +153,7 @@ class dynamic_format_arg_store
|
|||
*/
|
||||
template <typename T> void push_back(const T& arg) {
|
||||
if (detail::const_check(need_copy<T>::value))
|
||||
emplace_arg(dynamic_args_.push<stored_type<T>>(arg));
|
||||
emplace_arg(dynamic_args_.push<stored_t<T>>(arg));
|
||||
else
|
||||
emplace_arg(detail::unwrap(arg));
|
||||
}
|
||||
|
@ -200,7 +189,7 @@ class dynamic_format_arg_store
|
|||
dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str();
|
||||
if (detail::const_check(need_copy<T>::value)) {
|
||||
emplace_arg(
|
||||
fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value)));
|
||||
fmt::arg(arg_name, dynamic_args_.push<stored_t<T>>(arg.value)));
|
||||
} else {
|
||||
emplace_arg(fmt::arg(arg_name, arg.value));
|
||||
}
|
||||
|
@ -210,17 +199,20 @@ class dynamic_format_arg_store
|
|||
void clear() {
|
||||
data_.clear();
|
||||
named_info_.clear();
|
||||
dynamic_args_ = detail::dynamic_arg_list();
|
||||
dynamic_args_ = {};
|
||||
}
|
||||
|
||||
/// Reserves space to store at least `new_cap` arguments including
|
||||
/// `new_cap_named` named arguments.
|
||||
void reserve(size_t new_cap, size_t new_cap_named) {
|
||||
FMT_ASSERT(new_cap >= new_cap_named,
|
||||
"Set of arguments includes set of named arguments");
|
||||
"set of arguments includes set of named arguments");
|
||||
data_.reserve(new_cap);
|
||||
named_info_.reserve(new_cap_named);
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the store.
|
||||
size_t size() const noexcept { return data_.size(); }
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
|
|
@ -330,7 +330,7 @@ FMT_CONSTEXPR inline auto operator|(emphasis lhs, emphasis rhs) noexcept
|
|||
namespace detail {
|
||||
|
||||
template <typename Char> struct ansi_color_escape {
|
||||
FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
|
||||
FMT_CONSTEXPR ansi_color_escape(color_type text_color,
|
||||
const char* esc) noexcept {
|
||||
// If we have a terminal color, we need to output another escape code
|
||||
// sequence.
|
||||
|
@ -412,13 +412,13 @@ template <typename Char> struct ansi_color_escape {
|
|||
};
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR auto make_foreground_color(detail::color_type foreground) noexcept
|
||||
FMT_CONSTEXPR auto make_foreground_color(color_type foreground) noexcept
|
||||
-> ansi_color_escape<Char> {
|
||||
return ansi_color_escape<Char>(foreground, "\x1b[38;2;");
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR auto make_background_color(detail::color_type background) noexcept
|
||||
FMT_CONSTEXPR auto make_background_color(color_type background) noexcept
|
||||
-> ansi_color_escape<Char> {
|
||||
return ansi_color_escape<Char>(background, "\x1b[48;2;");
|
||||
}
|
||||
|
@ -434,36 +434,35 @@ template <typename Char> inline void reset_color(buffer<Char>& buffer) {
|
|||
buffer.append(reset_color.begin(), reset_color.end());
|
||||
}
|
||||
|
||||
template <typename T> struct styled_arg : detail::view {
|
||||
template <typename T> struct styled_arg : view {
|
||||
const T& value;
|
||||
text_style style;
|
||||
styled_arg(const T& v, text_style s) : value(v), style(s) {}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
void vformat_to(
|
||||
buffer<Char>& buf, const text_style& ts, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffered_context<type_identity_t<Char>>> args) {
|
||||
void vformat_to(buffer<Char>& buf, const text_style& ts,
|
||||
basic_string_view<Char> fmt,
|
||||
basic_format_args<buffered_context<Char>> args) {
|
||||
bool has_style = false;
|
||||
if (ts.has_emphasis()) {
|
||||
has_style = true;
|
||||
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
|
||||
auto emphasis = make_emphasis<Char>(ts.get_emphasis());
|
||||
buf.append(emphasis.begin(), emphasis.end());
|
||||
}
|
||||
if (ts.has_foreground()) {
|
||||
has_style = true;
|
||||
auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());
|
||||
auto foreground = make_foreground_color<Char>(ts.get_foreground());
|
||||
buf.append(foreground.begin(), foreground.end());
|
||||
}
|
||||
if (ts.has_background()) {
|
||||
has_style = true;
|
||||
auto background = detail::make_background_color<Char>(ts.get_background());
|
||||
auto background = make_background_color<Char>(ts.get_background());
|
||||
buf.append(background.begin(), background.end());
|
||||
}
|
||||
detail::vformat_to(buf, format_str, args, {});
|
||||
if (has_style) detail::reset_color<Char>(buf);
|
||||
vformat_to(buf, fmt, args);
|
||||
if (has_style) reset_color<Char>(buf);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline void vprint(FILE* f, const text_style& ts, string_view fmt,
|
||||
|
@ -485,7 +484,7 @@ inline void vprint(FILE* f, const text_style& ts, string_view fmt,
|
|||
template <typename... T>
|
||||
void print(FILE* f, const text_style& ts, format_string<T...> fmt,
|
||||
T&&... args) {
|
||||
vprint(f, ts, fmt, fmt::make_format_args(args...));
|
||||
vprint(f, ts, fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -524,7 +523,7 @@ inline auto vformat(const text_style& ts, string_view fmt, format_args args)
|
|||
template <typename... T>
|
||||
inline auto format(const text_style& ts, format_string<T...> fmt, T&&... args)
|
||||
-> std::string {
|
||||
return fmt::vformat(ts, fmt, fmt::make_format_args(args...));
|
||||
return fmt::vformat(ts, fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
/// Formats a string with the given text_style and writes the output to `out`.
|
||||
|
@ -551,7 +550,7 @@ template <typename OutputIt, typename... T,
|
|||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
|
||||
inline auto format_to(OutputIt out, const text_style& ts,
|
||||
format_string<T...> fmt, T&&... args) -> OutputIt {
|
||||
return vformat_to(out, ts, fmt, fmt::make_format_args(args...));
|
||||
return vformat_to(out, ts, fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
template <typename T, typename Char>
|
||||
|
@ -560,31 +559,30 @@ struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
|
|||
auto format(const detail::styled_arg<T>& arg, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
const auto& ts = arg.style;
|
||||
const auto& value = arg.value;
|
||||
auto out = ctx.out();
|
||||
|
||||
bool has_style = false;
|
||||
if (ts.has_emphasis()) {
|
||||
has_style = true;
|
||||
auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
|
||||
out = std::copy(emphasis.begin(), emphasis.end(), out);
|
||||
out = detail::copy<Char>(emphasis.begin(), emphasis.end(), out);
|
||||
}
|
||||
if (ts.has_foreground()) {
|
||||
has_style = true;
|
||||
auto foreground =
|
||||
detail::make_foreground_color<Char>(ts.get_foreground());
|
||||
out = std::copy(foreground.begin(), foreground.end(), out);
|
||||
out = detail::copy<Char>(foreground.begin(), foreground.end(), out);
|
||||
}
|
||||
if (ts.has_background()) {
|
||||
has_style = true;
|
||||
auto background =
|
||||
detail::make_background_color<Char>(ts.get_background());
|
||||
out = std::copy(background.begin(), background.end(), out);
|
||||
out = detail::copy<Char>(background.begin(), background.end(), out);
|
||||
}
|
||||
out = formatter<T, Char>::format(value, ctx);
|
||||
out = formatter<T, Char>::format(arg.value, ctx);
|
||||
if (has_style) {
|
||||
auto reset_color = string_view("\x1b[0m");
|
||||
out = std::copy(reset_color.begin(), reset_color.end(), out);
|
||||
out = detail::copy<Char>(reset_color.begin(), reset_color.end(), out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -19,17 +19,11 @@ FMT_BEGIN_NAMESPACE
|
|||
// A compile-time string which is compiled into fast formatting code.
|
||||
FMT_EXPORT class compiled_string {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T, typename InputIt>
|
||||
FMT_CONSTEXPR inline auto copy(InputIt begin, InputIt end, counting_iterator it)
|
||||
-> counting_iterator {
|
||||
return it + (end - begin);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -42,22 +36,11 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {};
|
|||
* std::string s = fmt::format(FMT_COMPILE("{}"), 42);
|
||||
*/
|
||||
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
|
||||
# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::compiled_string, explicit)
|
||||
# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::compiled_string)
|
||||
#else
|
||||
# define FMT_COMPILE(s) FMT_STRING(s)
|
||||
#endif
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
template <typename Char, size_t N,
|
||||
fmt::detail_exported::fixed_string<Char, N> Str>
|
||||
struct udl_compiled_string : compiled_string {
|
||||
using char_type = Char;
|
||||
explicit constexpr operator basic_string_view<char_type>() const {
|
||||
return {Str.data, N - 1};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, typename... Tail>
|
||||
auto first(const T& value, const Tail&...) -> const T& {
|
||||
return value;
|
||||
|
@ -77,6 +60,29 @@ constexpr const auto& get([[maybe_unused]] const T& first,
|
|||
return detail::get<N - 1>(rest...);
|
||||
}
|
||||
|
||||
# if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
template <int N, typename T, typename... Args, typename Char>
|
||||
constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
|
||||
if constexpr (is_static_named_arg<T>()) {
|
||||
if (name == T::name) return N;
|
||||
}
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
return get_arg_index_by_name<N + 1, Args...>(name);
|
||||
(void)name; // Workaround an MSVC bug about "unused" parameter.
|
||||
return -1;
|
||||
}
|
||||
# endif
|
||||
|
||||
template <typename... Args, typename Char>
|
||||
FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
|
||||
# if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
if constexpr (sizeof...(Args) > 0)
|
||||
return get_arg_index_by_name<0, Args...>(name);
|
||||
# endif
|
||||
(void)name;
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename Char, typename... Args>
|
||||
constexpr int get_arg_index_by_name(basic_string_view<Char> name,
|
||||
type_list<Args...>) {
|
||||
|
@ -149,8 +155,9 @@ template <typename Char, typename T, int N> struct field {
|
|||
if constexpr (std::is_convertible<T, basic_string_view<Char>>::value) {
|
||||
auto s = basic_string_view<Char>(arg);
|
||||
return copy<Char>(s.begin(), s.end(), out);
|
||||
} else {
|
||||
return write<Char>(out, arg);
|
||||
}
|
||||
return write<Char>(out, arg);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -275,6 +282,7 @@ constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
|||
}
|
||||
|
||||
template <typename Char> struct arg_id_handler {
|
||||
arg_id_kind kind;
|
||||
arg_ref<Char> arg_id;
|
||||
|
||||
constexpr int on_auto() {
|
||||
|
@ -282,25 +290,28 @@ template <typename Char> struct arg_id_handler {
|
|||
return 0;
|
||||
}
|
||||
constexpr int on_index(int id) {
|
||||
kind = arg_id_kind::index;
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
}
|
||||
constexpr int on_name(basic_string_view<Char> id) {
|
||||
kind = arg_id_kind::name;
|
||||
arg_id = arg_ref<Char>(id);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct parse_arg_id_result {
|
||||
arg_id_kind kind;
|
||||
arg_ref<Char> arg_id;
|
||||
const Char* arg_id_end;
|
||||
};
|
||||
|
||||
template <int ID, typename Char>
|
||||
constexpr auto parse_arg_id(const Char* begin, const Char* end) {
|
||||
auto handler = arg_id_handler<Char>{arg_ref<Char>{}};
|
||||
auto handler = arg_id_handler<Char>{arg_id_kind::none, arg_ref<Char>{}};
|
||||
auto arg_id_end = parse_arg_id(begin, end, handler);
|
||||
return parse_arg_id_result<Char>{handler.arg_id, arg_id_end};
|
||||
return parse_arg_id_result<Char>{handler.kind, handler.arg_id, arg_id_end};
|
||||
}
|
||||
|
||||
template <typename T, typename Enable = void> struct field_type {
|
||||
|
@ -363,18 +374,18 @@ constexpr auto compile_format_string(S fmt) {
|
|||
constexpr char_type c =
|
||||
arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type();
|
||||
static_assert(c == '}' || c == ':', "missing '}' in format string");
|
||||
if constexpr (arg_id_result.arg_id.kind == arg_id_kind::index) {
|
||||
if constexpr (arg_id_result.kind == arg_id_kind::index) {
|
||||
static_assert(
|
||||
ID == manual_indexing_id || ID == 0,
|
||||
"cannot switch from automatic to manual argument indexing");
|
||||
constexpr auto arg_index = arg_id_result.arg_id.val.index;
|
||||
constexpr auto arg_index = arg_id_result.arg_id.index;
|
||||
return parse_replacement_field_then_tail<get_type<arg_index, Args>,
|
||||
Args, arg_id_end_pos,
|
||||
arg_index, manual_indexing_id>(
|
||||
fmt);
|
||||
} else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) {
|
||||
} else if constexpr (arg_id_result.kind == arg_id_kind::name) {
|
||||
constexpr auto arg_index =
|
||||
get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{});
|
||||
get_arg_index_by_name(arg_id_result.arg_id.name, Args{});
|
||||
if constexpr (arg_index >= 0) {
|
||||
constexpr auto next_id =
|
||||
ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
|
||||
|
@ -383,8 +394,7 @@ constexpr auto compile_format_string(S fmt) {
|
|||
arg_index, next_id>(fmt);
|
||||
} else if constexpr (c == '}') {
|
||||
return parse_tail<Args, arg_id_end_pos + 1, ID>(
|
||||
runtime_named_field<char_type>{arg_id_result.arg_id.val.name},
|
||||
fmt);
|
||||
runtime_named_field<char_type>{arg_id_result.arg_id.name}, fmt);
|
||||
} else if constexpr (c == ':') {
|
||||
return unknown_format(); // no type info for specs parsing
|
||||
}
|
||||
|
@ -405,7 +415,7 @@ constexpr auto compile_format_string(S fmt) {
|
|||
}
|
||||
|
||||
template <typename... Args, typename S,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
constexpr auto compile(S fmt) {
|
||||
constexpr auto str = basic_string_view<typename S::char_type>(fmt);
|
||||
if constexpr (str.size() == 0) {
|
||||
|
@ -441,7 +451,7 @@ constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
|||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||
Args&&... args) {
|
||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
||||
|
@ -468,7 +478,7 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
|||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
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());
|
||||
if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
|
||||
|
@ -483,7 +493,7 @@ FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
|
|||
#endif
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
using traits = detail::fixed_buffer_traits;
|
||||
|
@ -493,32 +503,32 @@ auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args)
|
|||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args)
|
||||
-> size_t {
|
||||
return fmt::format_to(detail::counting_iterator(), fmt, args...).count();
|
||||
auto buf = detail::counting_buffer<>();
|
||||
fmt::format_to(appender(buf), fmt, args...);
|
||||
return buf.count();
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
void print(std::FILE* f, const S& fmt, const Args&... args) {
|
||||
memory_buffer buffer;
|
||||
fmt::format_to(std::back_inserter(buffer), fmt, args...);
|
||||
detail::print(f, {buffer.data(), buffer.size()});
|
||||
auto buf = memory_buffer();
|
||||
fmt::format_to(appender(buf), fmt, args...);
|
||||
detail::print(f, {buf.data(), buf.size()});
|
||||
}
|
||||
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_ENABLE_IF(is_compiled_string<S>::value)>
|
||||
void print(const S& fmt, const Args&... args) {
|
||||
print(stdout, fmt, args...);
|
||||
}
|
||||
|
||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
inline namespace literals {
|
||||
template <detail_exported::fixed_string Str> constexpr auto operator""_cf() {
|
||||
using char_t = remove_cvref_t<decltype(Str.data[0])>;
|
||||
return detail::udl_compiled_string<char_t, sizeof(Str.data) / sizeof(char_t),
|
||||
Str>();
|
||||
template <detail::fixed_string Str> constexpr auto operator""_cf() {
|
||||
return FMT_COMPILE(Str.data);
|
||||
}
|
||||
} // namespace literals
|
||||
#endif
|
||||
|
|
|
@ -14,10 +14,6 @@
|
|||
# include <climits>
|
||||
# include <cmath>
|
||||
# include <exception>
|
||||
|
||||
# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||
# include <locale>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE)
|
||||
|
@ -26,16 +22,22 @@
|
|||
|
||||
#include "format.h"
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
# include <locale>
|
||||
#endif
|
||||
|
||||
#ifndef FMT_FUNC
|
||||
# define FMT_FUNC
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
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
|
||||
std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
|
||||
// Chosen instead of std::abort to satisfy Clang in CUDA mode during device
|
||||
// code pass.
|
||||
std::terminate();
|
||||
// writing to stderr fails.
|
||||
fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
|
||||
abort();
|
||||
}
|
||||
|
||||
FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
|
||||
|
@ -61,86 +63,95 @@ FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
|
|||
FMT_ASSERT(out.size() <= inline_buffer_size, "");
|
||||
}
|
||||
|
||||
FMT_FUNC void report_error(format_func func, int error_code,
|
||||
const char* message) noexcept {
|
||||
FMT_FUNC void do_report_error(format_func func, int error_code,
|
||||
const char* message) noexcept {
|
||||
memory_buffer full_message;
|
||||
func(full_message, error_code, message);
|
||||
// Don't use fwrite_fully because the latter may throw.
|
||||
// Don't use fwrite_all because the latter may throw.
|
||||
if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0)
|
||||
std::fputc('\n', stderr);
|
||||
}
|
||||
|
||||
// A wrapper around fwrite that throws on error.
|
||||
inline void fwrite_fully(const void* ptr, size_t count, FILE* stream) {
|
||||
inline void fwrite_all(const void* ptr, size_t count, FILE* stream) {
|
||||
size_t written = std::fwrite(ptr, 1, count, stream);
|
||||
if (written < count)
|
||||
FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
|
||||
}
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
#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, std::locale>::value, "");
|
||||
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, std::locale>::value, "");
|
||||
return locale_ ? *static_cast<const std::locale*>(locale_) : std::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 = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
|
||||
auto&& facet = use_facet<numpunct<Char>>(loc.get<locale>());
|
||||
auto grouping = facet.grouping();
|
||||
auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
|
||||
return {std::move(grouping), thousands_sep};
|
||||
}
|
||||
template <typename Char>
|
||||
FMT_FUNC auto decimal_point_impl(locale_ref loc) -> Char {
|
||||
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
|
||||
.decimal_point();
|
||||
return use_facet<numpunct<Char>>(loc.get<locale>()).decimal_point();
|
||||
}
|
||||
#else
|
||||
template <typename Char>
|
||||
FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
|
||||
return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
|
||||
}
|
||||
template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
|
||||
return '.';
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
FMT_FUNC auto write_loc(appender out, loc_value value,
|
||||
const format_specs& specs, locale_ref loc) -> bool {
|
||||
#ifdef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
value.visit(loc_writer<>{
|
||||
out, specs, std::string(1, FMT_STATIC_THOUSANDS_SEPARATOR), "\3", "."});
|
||||
return true;
|
||||
#else
|
||||
auto locale = loc.get<std::locale>();
|
||||
// We cannot use the num_put<char> facet because it may produce output in
|
||||
// a wrong encoding.
|
||||
using facet = format_facet<std::locale>;
|
||||
if (std::has_facet<facet>(locale))
|
||||
return std::use_facet<facet>(locale).put(out, value, specs);
|
||||
return use_facet<facet>(locale).put(out, value, specs);
|
||||
return facet(locale).put(out, value, specs);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} // 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();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Locale> typename Locale::id format_facet<Locale>::id;
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
template <typename Locale> format_facet<Locale>::format_facet(Locale& loc) {
|
||||
auto& numpunct = std::use_facet<std::numpunct<char>>(loc);
|
||||
grouping_ = numpunct.grouping();
|
||||
if (!grouping_.empty()) separator_ = std::string(1, numpunct.thousands_sep());
|
||||
auto& np = detail::use_facet<detail::numpunct<char>>(loc);
|
||||
grouping_ = np.grouping();
|
||||
if (!grouping_.empty()) separator_ = std::string(1, np.thousands_sep());
|
||||
}
|
||||
|
||||
#if FMT_USE_LOCALE
|
||||
template <>
|
||||
FMT_API FMT_FUNC auto format_facet<std::locale>::do_put(
|
||||
appender out, loc_value val, const format_specs& specs) const -> bool {
|
||||
|
@ -1425,7 +1436,7 @@ FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
|
|||
|
||||
FMT_FUNC void report_system_error(int error_code,
|
||||
const char* message) noexcept {
|
||||
report_error(format_system_error, error_code, message);
|
||||
do_report_error(format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string {
|
||||
|
@ -1438,6 +1449,15 @@ FMT_FUNC auto vformat(string_view fmt, format_args args) -> std::string {
|
|||
|
||||
namespace detail {
|
||||
|
||||
FMT_FUNC void vformat_to(buffer<char>& buf, string_view fmt, format_args args,
|
||||
locale_ref loc) {
|
||||
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}});
|
||||
}
|
||||
|
||||
template <typename T> struct span {
|
||||
T* data;
|
||||
size_t size;
|
||||
|
@ -1508,6 +1528,7 @@ template <typename F> class glibc_file : public file_base<F> {
|
|||
void init_buffer() {
|
||||
if (this->file_->_IO_write_ptr) return;
|
||||
// Force buffer initialization by placing and removing a char in a buffer.
|
||||
assume(this->file_->_IO_write_ptr >= this->file_->_IO_write_end);
|
||||
putc_unlocked(0, this->file_);
|
||||
--this->file_->_IO_write_ptr;
|
||||
}
|
||||
|
@ -1615,7 +1636,7 @@ template <typename F> class fallback_file : public file_base<F> {
|
|||
};
|
||||
|
||||
#ifndef FMT_USE_FALLBACK_FILE
|
||||
# define FMT_USE_FALLBACK_FILE 1
|
||||
# define FMT_USE_FALLBACK_FILE 0
|
||||
#endif
|
||||
|
||||
template <typename F,
|
||||
|
@ -1692,7 +1713,7 @@ FMT_FUNC void vprint_mojibake(std::FILE* f, string_view fmt, format_args args,
|
|||
auto buffer = memory_buffer();
|
||||
detail::vformat_to(buffer, fmt, args);
|
||||
if (newline) buffer.push_back('\n');
|
||||
fwrite_fully(buffer.data(), buffer.size(), f);
|
||||
fwrite_all(buffer.data(), buffer.size(), f);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1704,7 +1725,7 @@ FMT_FUNC void print(std::FILE* f, string_view text) {
|
|||
if (write_console(fd, text)) return;
|
||||
}
|
||||
#endif
|
||||
fwrite_fully(text.data(), text.size(), f);
|
||||
fwrite_all(text.data(), text.size(), f);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ FMT_API void format_windows_error(buffer<char>& out, int error_code,
|
|||
const char* message) noexcept;
|
||||
}
|
||||
|
||||
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
||||
FMT_API std::system_error vwindows_error(int error_code, string_view fmt,
|
||||
format_args args);
|
||||
|
||||
/**
|
||||
|
@ -146,10 +146,10 @@ FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
|
|||
* "cannot open file '{}'", filename);
|
||||
* }
|
||||
*/
|
||||
template <typename... Args>
|
||||
std::system_error windows_error(int error_code, string_view message,
|
||||
const Args&... args) {
|
||||
return vwindows_error(error_code, message, fmt::make_format_args(args...));
|
||||
template <typename... T>
|
||||
auto windows_error(int error_code, string_view message, const T&... args)
|
||||
-> std::system_error {
|
||||
return vwindows_error(error_code, message, vargs<T...>{{args...}});
|
||||
}
|
||||
|
||||
// Reports a Windows error without throwing an exception.
|
||||
|
@ -164,8 +164,8 @@ inline auto system_category() noexcept -> const std::error_category& {
|
|||
// std::system is not available on some platforms such as iOS (#2248).
|
||||
#ifdef __OSX__
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
void say(const S& format_str, Args&&... args) {
|
||||
std::system(format("say \"{}\"", format(format_str, args...)).c_str());
|
||||
void say(const S& fmt, Args&&... args) {
|
||||
std::system(format("say \"{}\"", format(fmt, args...)).c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -176,24 +176,24 @@ class buffered_file {
|
|||
|
||||
friend class file;
|
||||
|
||||
explicit buffered_file(FILE* f) : file_(f) {}
|
||||
inline explicit buffered_file(FILE* f) : file_(f) {}
|
||||
|
||||
public:
|
||||
buffered_file(const buffered_file&) = delete;
|
||||
void operator=(const buffered_file&) = delete;
|
||||
|
||||
// Constructs a buffered_file object which doesn't represent any file.
|
||||
buffered_file() noexcept : file_(nullptr) {}
|
||||
inline buffered_file() noexcept : file_(nullptr) {}
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
FMT_API ~buffered_file() noexcept;
|
||||
|
||||
public:
|
||||
buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
|
||||
inline buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
|
||||
auto operator=(buffered_file&& other) -> buffered_file& {
|
||||
inline auto operator=(buffered_file&& other) -> buffered_file& {
|
||||
close();
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
|
@ -207,13 +207,13 @@ class buffered_file {
|
|||
FMT_API void close();
|
||||
|
||||
// Returns the pointer to a FILE object representing this file.
|
||||
auto get() const noexcept -> FILE* { return file_; }
|
||||
inline auto get() const noexcept -> FILE* { return file_; }
|
||||
|
||||
FMT_API auto descriptor() const -> int;
|
||||
|
||||
template <typename... T>
|
||||
inline void print(string_view fmt, const T&... args) {
|
||||
const auto& vargs = fmt::make_format_args(args...);
|
||||
fmt::vargs<T...> vargs = {{args...}};
|
||||
detail::is_locking<T...>() ? fmt::vprint_buffered(file_, fmt, vargs)
|
||||
: fmt::vprint(file_, fmt, vargs);
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ class FMT_API file {
|
|||
};
|
||||
|
||||
// Constructs a file object which doesn't represent any file.
|
||||
file() noexcept : fd_(-1) {}
|
||||
inline file() noexcept : fd_(-1) {}
|
||||
|
||||
// Opens a file and constructs a file object representing this file.
|
||||
file(cstring_view path, int oflag);
|
||||
|
@ -257,10 +257,10 @@ class FMT_API file {
|
|||
file(const file&) = delete;
|
||||
void operator=(const file&) = delete;
|
||||
|
||||
file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
|
||||
inline file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
|
||||
|
||||
// Move assignment is not noexcept because close may throw.
|
||||
auto operator=(file&& other) -> file& {
|
||||
inline auto operator=(file&& other) -> file& {
|
||||
close();
|
||||
fd_ = other.fd_;
|
||||
other.fd_ = -1;
|
||||
|
@ -271,7 +271,7 @@ class FMT_API file {
|
|||
~file() noexcept;
|
||||
|
||||
// Returns the file descriptor.
|
||||
auto descriptor() const noexcept -> int { return fd_; }
|
||||
inline auto descriptor() const noexcept -> int { return fd_; }
|
||||
|
||||
// Closes the file.
|
||||
void close();
|
||||
|
@ -324,9 +324,9 @@ auto getpagesize() -> long;
|
|||
namespace detail {
|
||||
|
||||
struct buffer_size {
|
||||
buffer_size() = default;
|
||||
constexpr buffer_size() = default;
|
||||
size_t value = 0;
|
||||
auto operator=(size_t val) const -> buffer_size {
|
||||
FMT_CONSTEXPR auto operator=(size_t val) const -> buffer_size {
|
||||
auto bs = buffer_size();
|
||||
bs.value = val;
|
||||
return bs;
|
||||
|
@ -337,7 +337,7 @@ struct ostream_params {
|
|||
int oflag = file::WRONLY | file::CREATE | file::TRUNC;
|
||||
size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
|
||||
|
||||
ostream_params() {}
|
||||
constexpr ostream_params() {}
|
||||
|
||||
template <typename... T>
|
||||
ostream_params(T... params, int new_oflag) : ostream_params(params...) {
|
||||
|
@ -358,59 +358,47 @@ struct ostream_params {
|
|||
# endif
|
||||
};
|
||||
|
||||
class file_buffer final : public buffer<char> {
|
||||
} // namespace detail
|
||||
|
||||
FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size();
|
||||
|
||||
/// A fast buffered output stream for writing from a single thread. Writing from
|
||||
/// multiple threads without external synchronization may result in a data race.
|
||||
class FMT_API ostream : private detail::buffer<char> {
|
||||
private:
|
||||
file file_;
|
||||
|
||||
FMT_API static void grow(buffer<char>& buf, size_t);
|
||||
ostream(cstring_view path, const detail::ostream_params& params);
|
||||
|
||||
static void grow(buffer<char>& buf, size_t);
|
||||
|
||||
public:
|
||||
FMT_API file_buffer(cstring_view path, const ostream_params& params);
|
||||
FMT_API file_buffer(file_buffer&& other) noexcept;
|
||||
FMT_API ~file_buffer();
|
||||
ostream(ostream&& other) noexcept;
|
||||
~ostream();
|
||||
|
||||
void flush() {
|
||||
operator writer() {
|
||||
detail::buffer<char>& buf = *this;
|
||||
return buf;
|
||||
}
|
||||
|
||||
inline void flush() {
|
||||
if (size() == 0) return;
|
||||
file_.write(data(), size() * sizeof(data()[0]));
|
||||
clear();
|
||||
}
|
||||
|
||||
void close() {
|
||||
flush();
|
||||
file_.close();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
constexpr auto buffer_size = detail::buffer_size();
|
||||
|
||||
/// A fast output stream for writing from a single thread. Writing from
|
||||
/// multiple threads without external synchronization may result in a data race.
|
||||
class FMT_API ostream {
|
||||
private:
|
||||
FMT_MSC_WARNING(suppress : 4251)
|
||||
detail::file_buffer buffer_;
|
||||
|
||||
ostream(cstring_view path, const detail::ostream_params& params)
|
||||
: buffer_(path, params) {}
|
||||
|
||||
public:
|
||||
ostream(ostream&& other) : buffer_(std::move(other.buffer_)) {}
|
||||
|
||||
~ostream();
|
||||
|
||||
void flush() { buffer_.flush(); }
|
||||
|
||||
template <typename... T>
|
||||
friend auto output_file(cstring_view path, T... params) -> ostream;
|
||||
|
||||
void close() { buffer_.close(); }
|
||||
inline void close() {
|
||||
flush();
|
||||
file_.close();
|
||||
}
|
||||
|
||||
/// Formats `args` according to specifications in `fmt` and writes the
|
||||
/// output to the file.
|
||||
template <typename... T> void print(format_string<T...> fmt, T&&... args) {
|
||||
vformat_to(appender(buffer_), fmt, fmt::make_format_args(args...));
|
||||
vformat_to(appender(*this), fmt.str, vargs<T...>{{args...}});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,14 @@
|
|||
|
||||
#include "chrono.h" // formatbuf
|
||||
|
||||
#ifdef _MSVC_STL_UPDATE
|
||||
# define FMT_MSVC_STL_UPDATE _MSVC_STL_UPDATE
|
||||
#elif defined(_MSC_VER) && _MSC_VER < 1912 // VS 15.5
|
||||
# define FMT_MSVC_STL_UPDATE _MSVC_LANG
|
||||
#else
|
||||
# define FMT_MSVC_STL_UPDATE 0
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
|
||||
|
@ -35,53 +43,18 @@ class file_access {
|
|||
friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
|
||||
};
|
||||
|
||||
#if FMT_MSC_VERSION
|
||||
#if FMT_MSVC_STL_UPDATE
|
||||
template class file_access<file_access_tag, std::filebuf,
|
||||
&std::filebuf::_Myfile>;
|
||||
auto get_file(std::filebuf&) -> FILE*;
|
||||
#endif
|
||||
|
||||
inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data)
|
||||
-> bool {
|
||||
FILE* f = nullptr;
|
||||
#if FMT_MSC_VERSION && FMT_USE_RTTI
|
||||
if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
|
||||
f = get_file(*buf);
|
||||
else
|
||||
return false;
|
||||
#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI
|
||||
auto* rdbuf = os.rdbuf();
|
||||
if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
|
||||
f = sfbuf->file();
|
||||
else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
|
||||
f = fbuf->file();
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
ignore_unused(os, data, f);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
if (f) {
|
||||
int fd = _fileno(f);
|
||||
if (_isatty(fd)) {
|
||||
os.flush();
|
||||
return write_console(fd, data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
inline auto write_ostream_unicode(std::wostream&,
|
||||
fmt::basic_string_view<wchar_t>) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write the content of buf to os.
|
||||
// It is a separate function rather than a part of vprint to simplify testing.
|
||||
template <typename Char>
|
||||
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
||||
const Char* buf_data = buf.data();
|
||||
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
||||
using unsigned_streamsize = make_unsigned_t<std::streamsize>;
|
||||
unsigned_streamsize size = buf.size();
|
||||
unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
|
||||
do {
|
||||
|
@ -92,21 +65,9 @@ void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
|||
} while (size != 0);
|
||||
}
|
||||
|
||||
template <typename Char, typename T>
|
||||
void format_value(buffer<Char>& buf, const T& value) {
|
||||
auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
|
||||
auto&& output = std::basic_ostream<Char>(&format_buf);
|
||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||
output.imbue(std::locale::classic()); // The default is always unlocalized.
|
||||
#endif
|
||||
output << value;
|
||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
}
|
||||
|
||||
template <typename T> struct streamed_view {
|
||||
const T& value;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
|
@ -117,7 +78,11 @@ struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
|
|||
template <typename T, typename Context>
|
||||
auto format(const T& value, Context& ctx) const -> decltype(ctx.out()) {
|
||||
auto buffer = basic_memory_buffer<Char>();
|
||||
detail::format_value(buffer, value);
|
||||
auto&& formatbuf = detail::formatbuf<std::basic_streambuf<Char>>(buffer);
|
||||
auto&& output = std::basic_ostream<Char>(&formatbuf);
|
||||
output.imbue(std::locale::classic()); // The default is always unlocalized.
|
||||
output << value;
|
||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
return formatter<basic_string_view<Char>, Char>::format(
|
||||
{buffer.data(), buffer.size()}, ctx);
|
||||
}
|
||||
|
@ -148,24 +113,30 @@ constexpr auto streamed(const T& value) -> detail::streamed_view<T> {
|
|||
return {value};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline void vprint_directly(std::ostream& os, string_view format_str,
|
||||
format_args args) {
|
||||
inline void vprint(std::ostream& os, string_view fmt, format_args args) {
|
||||
auto buffer = memory_buffer();
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
detail::write_buffer(os, buffer);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
FMT_EXPORT template <typename Char>
|
||||
void vprint(std::basic_ostream<Char>& os,
|
||||
basic_string_view<type_identity_t<Char>> format_str,
|
||||
typename detail::vformat_args<Char>::type args) {
|
||||
auto buffer = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buffer, format_str, args);
|
||||
if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return;
|
||||
detail::vformat_to(buffer, fmt, args);
|
||||
FILE* f = nullptr;
|
||||
#if FMT_MSVC_STL_UPDATE && FMT_USE_RTTI
|
||||
if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
|
||||
f = detail::get_file(*buf);
|
||||
#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI
|
||||
auto* rdbuf = os.rdbuf();
|
||||
if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
|
||||
f = sfbuf->file();
|
||||
else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
|
||||
f = fbuf->file();
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
if (f) {
|
||||
int fd = _fileno(f);
|
||||
if (_isatty(fd)) {
|
||||
os.flush();
|
||||
if (detail::write_console(fd, {buffer.data(), buffer.size()})) return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
detail::ignore_unused(f);
|
||||
detail::write_buffer(os, buffer);
|
||||
}
|
||||
|
||||
|
@ -178,19 +149,11 @@ void vprint(std::basic_ostream<Char>& os,
|
|||
*/
|
||||
FMT_EXPORT template <typename... T>
|
||||
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
||||
const auto& vargs = fmt::make_format_args(args...);
|
||||
if (detail::use_utf8())
|
||||
vprint(os, fmt, vargs);
|
||||
else
|
||||
detail::vprint_directly(os, fmt, vargs);
|
||||
}
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename... Args>
|
||||
void print(std::wostream& os,
|
||||
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
|
||||
Args&&... args) {
|
||||
vprint(os, fmt, fmt::make_format_args<buffered_context<wchar_t>>(args...));
|
||||
fmt::vargs<T...> vargs = {{args...}};
|
||||
if (detail::const_check(detail::use_utf8)) return vprint(os, fmt.str, vargs);
|
||||
auto buffer = memory_buffer();
|
||||
detail::vformat_to(buffer, fmt.str, vargs);
|
||||
detail::write_buffer(os, buffer);
|
||||
}
|
||||
|
||||
FMT_EXPORT template <typename... T>
|
||||
|
@ -198,14 +161,6 @@ void println(std::ostream& os, format_string<T...> fmt, T&&... args) {
|
|||
fmt::print(os, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
|
||||
}
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename... Args>
|
||||
void println(std::wostream& os,
|
||||
basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
|
||||
Args&&... args) {
|
||||
print(os, L"{}\n", fmt::format(fmt, std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_OSTREAM_H_
|
||||
|
|
|
@ -33,8 +33,9 @@ template <typename Char> class basic_printf_context {
|
|||
|
||||
public:
|
||||
using char_type = Char;
|
||||
using parse_context_type = basic_format_parse_context<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
|
||||
/// stored in the context object so make sure they have appropriate lifetimes.
|
||||
|
@ -54,6 +55,23 @@ template <typename Char> class basic_printf_context {
|
|||
|
||||
namespace detail {
|
||||
|
||||
// Return the result via the out param to workaround gcc bug 77539.
|
||||
template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
|
||||
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool {
|
||||
for (out = first; out != last; ++out) {
|
||||
if (*out == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline auto find<false, char>(const char* first, const char* last, char value,
|
||||
const char*& out) -> bool {
|
||||
out =
|
||||
static_cast<const char*>(memchr(first, value, to_unsigned(last - first)));
|
||||
return out != nullptr;
|
||||
}
|
||||
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
template <bool IsSigned> struct int_checker {
|
||||
|
@ -61,7 +79,7 @@ template <bool IsSigned> struct int_checker {
|
|||
unsigned max = to_unsigned(max_value<int>());
|
||||
return value <= max;
|
||||
}
|
||||
static auto fits_in_int(bool) -> bool { return true; }
|
||||
inline static auto fits_in_int(bool) -> bool { return true; }
|
||||
};
|
||||
|
||||
template <> struct int_checker<true> {
|
||||
|
@ -69,7 +87,7 @@ template <> struct int_checker<true> {
|
|||
return value >= (std::numeric_limits<int>::min)() &&
|
||||
value <= max_value<int>();
|
||||
}
|
||||
static auto fits_in_int(int) -> bool { return true; }
|
||||
inline static auto fits_in_int(int) -> bool { return true; }
|
||||
};
|
||||
|
||||
struct printf_precision_handler {
|
||||
|
@ -127,25 +145,19 @@ template <typename T, typename Context> class arg_converter {
|
|||
using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
|
||||
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
||||
// Extra casts are used to silence warnings.
|
||||
if (is_signed) {
|
||||
auto n = static_cast<int>(static_cast<target_type>(value));
|
||||
arg_ = detail::make_arg<Context>(n);
|
||||
} else {
|
||||
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
||||
auto n = static_cast<unsigned>(static_cast<unsigned_type>(value));
|
||||
arg_ = detail::make_arg<Context>(n);
|
||||
}
|
||||
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
||||
if (is_signed)
|
||||
arg_ = static_cast<int>(static_cast<target_type>(value));
|
||||
else
|
||||
arg_ = static_cast<unsigned>(static_cast<unsigned_type>(value));
|
||||
} else {
|
||||
if (is_signed) {
|
||||
// glibc's printf doesn't sign extend arguments of smaller types:
|
||||
// std::printf("%lld", -42); // prints "4294967254"
|
||||
// but we don't have to do the same because it's a UB.
|
||||
auto n = static_cast<long long>(value);
|
||||
arg_ = detail::make_arg<Context>(n);
|
||||
} else {
|
||||
auto n = static_cast<typename make_unsigned_or_bool<U>::type>(value);
|
||||
arg_ = detail::make_arg<Context>(n);
|
||||
}
|
||||
// glibc's printf doesn't sign extend arguments of smaller types:
|
||||
// std::printf("%lld", -42); // prints "4294967254"
|
||||
// but we don't have to do the same because it's a UB.
|
||||
if (is_signed)
|
||||
arg_ = static_cast<long long>(value);
|
||||
else
|
||||
arg_ = static_cast<typename make_unsigned_or_bool<U>::type>(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,8 +184,7 @@ template <typename Context> class char_converter {
|
|||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
void operator()(T value) {
|
||||
auto c = static_cast<typename Context::char_type>(value);
|
||||
arg_ = detail::make_arg<Context>(c);
|
||||
arg_ = static_cast<typename Context::char_type>(value);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
|
@ -194,13 +205,13 @@ class printf_width_handler {
|
|||
format_specs& specs_;
|
||||
|
||||
public:
|
||||
explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
|
||||
inline explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
auto operator()(T value) -> unsigned {
|
||||
auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
|
||||
if (detail::is_negative(value)) {
|
||||
specs_.align = align::left;
|
||||
specs_.set_align(align::left);
|
||||
width = 0 - width;
|
||||
}
|
||||
unsigned int_max = to_unsigned(max_value<int>());
|
||||
|
@ -234,69 +245,74 @@ class printf_arg_formatter : public arg_formatter<Char> {
|
|||
|
||||
void write_null_pointer(bool is_string = false) {
|
||||
auto s = this->specs;
|
||||
s.type = presentation_type::none;
|
||||
s.set_type(presentation_type::none);
|
||||
write_bytes<Char>(this->out, is_string ? "(null)" : "(nil)", s);
|
||||
}
|
||||
|
||||
template <typename T> void write(T value) {
|
||||
detail::write<Char>(this->out, value, this->specs, this->locale);
|
||||
}
|
||||
|
||||
public:
|
||||
printf_arg_formatter(basic_appender<Char> iter, format_specs& s,
|
||||
context_type& ctx)
|
||||
: base(make_arg_formatter(iter, s)), context_(ctx) {}
|
||||
|
||||
void operator()(monostate value) { base::operator()(value); }
|
||||
void operator()(monostate value) { write(value); }
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
|
||||
void operator()(T value) {
|
||||
// MSVC2013 fails to compile separate overloads for bool and Char so use
|
||||
// std::is_same instead.
|
||||
if (!std::is_same<T, Char>::value) {
|
||||
base::operator()(value);
|
||||
write(value);
|
||||
return;
|
||||
}
|
||||
format_specs s = this->specs;
|
||||
if (s.type != presentation_type::none && s.type != presentation_type::chr) {
|
||||
if (s.type() != presentation_type::none &&
|
||||
s.type() != presentation_type::chr) {
|
||||
return (*this)(static_cast<int>(value));
|
||||
}
|
||||
s.sign = sign::none;
|
||||
s.alt = false;
|
||||
s.fill = ' '; // Ignore '0' flag for char types.
|
||||
s.set_sign(sign::none);
|
||||
s.clear_alt();
|
||||
s.set_fill(' '); // Ignore '0' flag for char types.
|
||||
// align::numeric needs to be overwritten here since the '0' flag is
|
||||
// ignored for non-numeric types
|
||||
if (s.align == align::none || s.align == align::numeric)
|
||||
s.align = align::right;
|
||||
write<Char>(this->out, static_cast<Char>(value), s);
|
||||
if (s.align() == align::none || s.align() == align::numeric)
|
||||
s.set_align(align::right);
|
||||
detail::write<Char>(this->out, static_cast<Char>(value), s);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
void operator()(T value) {
|
||||
base::operator()(value);
|
||||
write(value);
|
||||
}
|
||||
|
||||
void operator()(const char* value) {
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
write(value);
|
||||
else
|
||||
write_null_pointer(this->specs.type != presentation_type::pointer);
|
||||
write_null_pointer(this->specs.type() != presentation_type::pointer);
|
||||
}
|
||||
|
||||
void operator()(const wchar_t* value) {
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
write(value);
|
||||
else
|
||||
write_null_pointer(this->specs.type != presentation_type::pointer);
|
||||
write_null_pointer(this->specs.type() != presentation_type::pointer);
|
||||
}
|
||||
|
||||
void operator()(basic_string_view<Char> value) { base::operator()(value); }
|
||||
void operator()(basic_string_view<Char> value) { write(value); }
|
||||
|
||||
void operator()(const void* value) {
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
write(value);
|
||||
else
|
||||
write_null_pointer();
|
||||
}
|
||||
|
||||
void operator()(typename basic_format_arg<context_type>::handle handle) {
|
||||
auto parse_ctx = basic_format_parse_context<Char>({});
|
||||
auto parse_ctx = parse_context<Char>({});
|
||||
handle.format(parse_ctx, context_);
|
||||
}
|
||||
};
|
||||
|
@ -305,23 +321,14 @@ template <typename Char>
|
|||
void parse_flags(format_specs& specs, const Char*& it, const Char* end) {
|
||||
for (; it != end; ++it) {
|
||||
switch (*it) {
|
||||
case '-':
|
||||
specs.align = align::left;
|
||||
break;
|
||||
case '+':
|
||||
specs.sign = sign::plus;
|
||||
break;
|
||||
case '0':
|
||||
specs.fill = '0';
|
||||
break;
|
||||
case '-': specs.set_align(align::left); break;
|
||||
case '+': specs.set_sign(sign::plus); break;
|
||||
case '0': specs.set_fill('0'); break;
|
||||
case ' ':
|
||||
if (specs.sign != sign::plus) specs.sign = sign::space;
|
||||
if (specs.sign() != sign::plus) specs.set_sign(sign::space);
|
||||
break;
|
||||
case '#':
|
||||
specs.alt = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
case '#': specs.set_alt(); break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +346,7 @@ auto parse_header(const Char*& it, const Char* end, format_specs& specs,
|
|||
++it;
|
||||
arg_index = value != -1 ? value : max_value<int>();
|
||||
} else {
|
||||
if (c == '0') specs.fill = '0';
|
||||
if (c == '0') specs.set_fill('0');
|
||||
if (value != 0) {
|
||||
// Nonzero value means that we parsed width and don't need to
|
||||
// parse it or flags again, so return now.
|
||||
|
@ -369,43 +376,22 @@ inline auto parse_printf_presentation_type(char c, type t, bool& upper)
|
|||
using pt = presentation_type;
|
||||
constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
|
||||
switch (c) {
|
||||
case 'd':
|
||||
return in(t, integral_set) ? pt::dec : pt::none;
|
||||
case 'o':
|
||||
return in(t, integral_set) ? pt::oct : pt::none;
|
||||
case 'X':
|
||||
upper = true;
|
||||
FMT_FALLTHROUGH;
|
||||
case 'x':
|
||||
return in(t, integral_set) ? pt::hex : pt::none;
|
||||
case 'E':
|
||||
upper = true;
|
||||
FMT_FALLTHROUGH;
|
||||
case 'e':
|
||||
return in(t, float_set) ? pt::exp : pt::none;
|
||||
case 'F':
|
||||
upper = true;
|
||||
FMT_FALLTHROUGH;
|
||||
case 'f':
|
||||
return in(t, float_set) ? pt::fixed : pt::none;
|
||||
case 'G':
|
||||
upper = true;
|
||||
FMT_FALLTHROUGH;
|
||||
case 'g':
|
||||
return in(t, float_set) ? pt::general : pt::none;
|
||||
case 'A':
|
||||
upper = true;
|
||||
FMT_FALLTHROUGH;
|
||||
case 'a':
|
||||
return in(t, float_set) ? pt::hexfloat : pt::none;
|
||||
case 'c':
|
||||
return in(t, integral_set) ? pt::chr : pt::none;
|
||||
case 's':
|
||||
return in(t, string_set | cstring_set) ? pt::string : pt::none;
|
||||
case 'p':
|
||||
return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none;
|
||||
default:
|
||||
return pt::none;
|
||||
case 'd': return in(t, integral_set) ? pt::dec : pt::none;
|
||||
case 'o': return in(t, integral_set) ? pt::oct : pt::none;
|
||||
case 'X': upper = true; FMT_FALLTHROUGH;
|
||||
case 'x': return in(t, integral_set) ? pt::hex : pt::none;
|
||||
case 'E': upper = true; FMT_FALLTHROUGH;
|
||||
case 'e': return in(t, float_set) ? pt::exp : pt::none;
|
||||
case 'F': upper = true; FMT_FALLTHROUGH;
|
||||
case 'f': return in(t, float_set) ? pt::fixed : pt::none;
|
||||
case 'G': upper = true; FMT_FALLTHROUGH;
|
||||
case 'g': return in(t, float_set) ? pt::general : pt::none;
|
||||
case 'A': upper = true; FMT_FALLTHROUGH;
|
||||
case 'a': return in(t, float_set) ? pt::hexfloat : pt::none;
|
||||
case 'c': return in(t, integral_set) ? pt::chr : pt::none;
|
||||
case 's': return in(t, string_set | cstring_set) ? pt::string : pt::none;
|
||||
case 'p': return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none;
|
||||
default: return pt::none;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,7 +401,7 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
|||
using iterator = basic_appender<Char>;
|
||||
auto out = iterator(buf);
|
||||
auto context = basic_printf_context<Char>(out, args);
|
||||
auto parse_ctx = basic_format_parse_context<Char>(format);
|
||||
auto parse_ctx = parse_context<Char>(format);
|
||||
|
||||
// Returns the argument with specified index or, if arg_index is -1, the next
|
||||
// argument.
|
||||
|
@ -444,7 +430,7 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
|||
write(out, basic_string_view<Char>(start, to_unsigned(it - 1 - start)));
|
||||
|
||||
auto specs = format_specs();
|
||||
specs.align = align::right;
|
||||
specs.set_align(align::right);
|
||||
|
||||
// Parse argument index, flags and width.
|
||||
int arg_index = parse_header(it, end, specs, get_arg);
|
||||
|
@ -468,9 +454,9 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
|||
auto arg = get_arg(arg_index);
|
||||
// For d, i, o, u, x, and X conversion specifiers, if a precision is
|
||||
// specified, the '0' flag is ignored
|
||||
if (specs.precision >= 0 && arg.is_integral()) {
|
||||
if (specs.precision >= 0 && is_integral_type(arg.type())) {
|
||||
// Ignore '0' for non-numeric types or if '-' present.
|
||||
specs.fill = ' ';
|
||||
specs.set_fill(' ');
|
||||
}
|
||||
if (specs.precision >= 0 && arg.type() == type::cstring_type) {
|
||||
auto str = arg.visit(get_cstring<Char>());
|
||||
|
@ -478,15 +464,16 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
|||
auto nul = std::find(str, str_end, Char());
|
||||
auto sv = basic_string_view<Char>(
|
||||
str, to_unsigned(nul != str_end ? nul - str : specs.precision));
|
||||
arg = make_arg<basic_printf_context<Char>>(sv);
|
||||
arg = sv;
|
||||
}
|
||||
if (specs.alt && arg.visit(is_zero_int())) specs.alt = false;
|
||||
if (specs.fill.template get<Char>() == '0') {
|
||||
if (arg.is_arithmetic() && specs.align != align::left)
|
||||
specs.align = align::numeric;
|
||||
else
|
||||
specs.fill = ' '; // Ignore '0' flag for non-numeric types or if '-'
|
||||
// flag is also present.
|
||||
if (specs.alt() && arg.visit(is_zero_int())) specs.clear_alt();
|
||||
if (specs.fill_unit<Char>() == '0') {
|
||||
if (is_arithmetic_type(arg.type()) && specs.align() != align::left) {
|
||||
specs.set_align(align::numeric);
|
||||
} else {
|
||||
// Ignore '0' flag for non-numeric types or if '-' flag is also present.
|
||||
specs.set_fill(' ');
|
||||
}
|
||||
}
|
||||
|
||||
// Parse length and convert the argument to the required type.
|
||||
|
@ -511,44 +498,34 @@ void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
|||
convert_arg<long>(arg, t);
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
convert_arg<intmax_t>(arg, t);
|
||||
break;
|
||||
case 'z':
|
||||
convert_arg<size_t>(arg, t);
|
||||
break;
|
||||
case 't':
|
||||
convert_arg<std::ptrdiff_t>(arg, t);
|
||||
break;
|
||||
case 'j': convert_arg<intmax_t>(arg, t); break;
|
||||
case 'z': convert_arg<size_t>(arg, t); break;
|
||||
case 't': convert_arg<std::ptrdiff_t>(arg, t); break;
|
||||
case 'L':
|
||||
// printf produces garbage when 'L' is omitted for long double, no
|
||||
// need to do the same.
|
||||
break;
|
||||
default:
|
||||
--it;
|
||||
convert_arg<void>(arg, c);
|
||||
default: --it; convert_arg<void>(arg, c);
|
||||
}
|
||||
|
||||
// Parse type.
|
||||
if (it == end) report_error("invalid format string");
|
||||
char type = static_cast<char>(*it++);
|
||||
if (arg.is_integral()) {
|
||||
if (is_integral_type(arg.type())) {
|
||||
// Normalize type.
|
||||
switch (type) {
|
||||
case 'i':
|
||||
case 'u':
|
||||
type = 'd';
|
||||
break;
|
||||
case 'u': type = 'd'; break;
|
||||
case 'c':
|
||||
arg.visit(char_converter<basic_printf_context<Char>>(arg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool upper = false;
|
||||
specs.type = parse_printf_presentation_type(type, arg.type(), upper);
|
||||
if (specs.type == presentation_type::none)
|
||||
specs.set_type(parse_printf_presentation_type(type, arg.type(), upper));
|
||||
if (specs.type() == presentation_type::none)
|
||||
report_error("invalid format specifier");
|
||||
specs.upper = upper;
|
||||
if (upper) specs.set_upper();
|
||||
|
||||
start = it;
|
||||
|
||||
|
@ -583,7 +560,7 @@ inline auto vsprintf(basic_string_view<Char> fmt,
|
|||
-> std::basic_string<Char> {
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vprintf(buf, fmt, args);
|
||||
return to_string(buf);
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -594,7 +571,7 @@ 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 = char_t<S>>
|
||||
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...));
|
||||
|
@ -619,7 +596,7 @@ 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 = char_t<S>>
|
||||
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...));
|
||||
|
|
|
@ -44,18 +44,6 @@ template <typename T> class is_set {
|
|||
!std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
|
||||
};
|
||||
|
||||
template <typename... Ts> struct conditional_helper {};
|
||||
|
||||
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
|
||||
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
|
||||
|
||||
# define FMT_DECLTYPE_RETURN(val) \
|
||||
->decltype(val) { return val; } \
|
||||
static_assert( \
|
||||
true, "") // This makes it so that a semicolon is required after the
|
||||
// macro, which helps clang-format handle the formatting.
|
||||
|
||||
// C array overload
|
||||
template <typename T, std::size_t N>
|
||||
auto range_begin(const T (&arr)[N]) -> const T* {
|
||||
|
@ -76,9 +64,13 @@ struct has_member_fn_begin_end_t<T, void_t<decltype(*std::declval<T>().begin()),
|
|||
|
||||
// Member function overloads.
|
||||
template <typename T>
|
||||
auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
|
||||
auto range_begin(T&& rng) -> decltype(static_cast<T&&>(rng).begin()) {
|
||||
return static_cast<T&&>(rng).begin();
|
||||
}
|
||||
template <typename T>
|
||||
auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
|
||||
auto range_end(T&& rng) -> decltype(static_cast<T&&>(rng).end()) {
|
||||
return static_cast<T&&>(rng).end();
|
||||
}
|
||||
|
||||
// ADL overloads. Only participate in overload resolution if member functions
|
||||
// are not found.
|
||||
|
@ -115,17 +107,16 @@ struct has_mutable_begin_end<
|
|||
// SFINAE properly unless there are distinct types
|
||||
int>> : std::true_type {};
|
||||
|
||||
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
|
||||
template <typename T>
|
||||
struct is_range_<T, void>
|
||||
: std::integral_constant<bool, (has_const_begin_end<T>::value ||
|
||||
has_mutable_begin_end<T>::value)> {};
|
||||
# undef FMT_DECLTYPE_RETURN
|
||||
#endif
|
||||
|
||||
// tuple_size and tuple_element check.
|
||||
template <typename T> class is_tuple_like_ {
|
||||
template <typename U>
|
||||
static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
|
||||
template <typename U, typename V = typename std::remove_cv<U>::type>
|
||||
static auto check(U* p) -> decltype(std::tuple_size<V>::value, 0);
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
|
@ -266,12 +257,12 @@ template <range_format K>
|
|||
using range_format_constant = std::integral_constant<range_format, K>;
|
||||
|
||||
// These are not generic lambdas for compatibility with C++11.
|
||||
template <typename ParseContext> struct parse_empty_specs {
|
||||
template <typename Char> struct parse_empty_specs {
|
||||
template <typename Formatter> FMT_CONSTEXPR void operator()(Formatter& f) {
|
||||
f.parse(ctx);
|
||||
detail::maybe_set_debug_format(f, true);
|
||||
}
|
||||
ParseContext& ctx;
|
||||
parse_context<Char>& ctx;
|
||||
};
|
||||
template <typename FormatContext> struct format_tuple_element {
|
||||
using char_type = typename FormatContext::char_type;
|
||||
|
@ -327,11 +318,17 @@ struct formatter<Tuple, Char,
|
|||
closing_bracket_ = close;
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
auto it = ctx.begin();
|
||||
if (it != ctx.end() && *it != '}') report_error("invalid format specifier");
|
||||
detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
|
||||
auto end = ctx.end();
|
||||
if (it != end && detail::to_ascii(*it) == 'n') {
|
||||
++it;
|
||||
set_brackets({}, {});
|
||||
set_separator({});
|
||||
}
|
||||
if (it != end && *it != '}') report_error("invalid format specifier");
|
||||
ctx.advance_to(it);
|
||||
detail::for_each(formatters_, detail::parse_empty_specs<Char>{ctx});
|
||||
return it;
|
||||
}
|
||||
|
||||
|
@ -352,38 +349,17 @@ template <typename T, typename Char> struct is_range {
|
|||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename Context> struct range_mapper {
|
||||
using mapper = arg_mapper<Context>;
|
||||
|
||||
template <typename T,
|
||||
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
|
||||
static auto map(T&& value) -> T&& {
|
||||
return static_cast<T&&>(value);
|
||||
}
|
||||
template <typename T,
|
||||
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
|
||||
static auto map(T&& value)
|
||||
-> decltype(mapper().map(static_cast<T&&>(value))) {
|
||||
return mapper().map(static_cast<T&&>(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Element>
|
||||
using range_formatter_type =
|
||||
formatter<remove_cvref_t<decltype(range_mapper<buffered_context<Char>>{}
|
||||
.map(std::declval<Element>()))>,
|
||||
Char>;
|
||||
using range_formatter_type = formatter<remove_cvref_t<Element>, Char>;
|
||||
|
||||
template <typename R>
|
||||
using maybe_const_range =
|
||||
conditional_t<has_const_begin_end<R>::value, const R, R>;
|
||||
|
||||
// Workaround a bug in MSVC 2015 and earlier.
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
|
||||
template <typename R, typename Char>
|
||||
struct is_formattable_delayed
|
||||
: is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
template <typename...> struct conjunction : std::true_type {};
|
||||
|
@ -415,7 +391,7 @@ struct range_formatter<
|
|||
auto buf = basic_memory_buffer<Char>();
|
||||
for (; it != end; ++it) buf.push_back(*it);
|
||||
auto specs = format_specs();
|
||||
specs.type = presentation_type::debug;
|
||||
specs.set_type(presentation_type::debug);
|
||||
return detail::write<Char>(
|
||||
out, basic_string_view<Char>(buf.data(), buf.size()), specs);
|
||||
}
|
||||
|
@ -443,8 +419,7 @@ struct range_formatter<
|
|||
closing_bracket_ = close;
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
detail::maybe_set_debug_format(underlying_, true);
|
||||
|
@ -486,7 +461,6 @@ struct range_formatter<
|
|||
|
||||
template <typename R, typename FormatContext>
|
||||
auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
auto mapper = detail::range_mapper<buffered_context<Char>>();
|
||||
auto out = ctx.out();
|
||||
auto it = detail::range_begin(range);
|
||||
auto end = detail::range_end(range);
|
||||
|
@ -498,7 +472,7 @@ struct range_formatter<
|
|||
if (i > 0) out = detail::copy<Char>(separator_, out);
|
||||
ctx.advance_to(out);
|
||||
auto&& item = *it; // Need an lvalue
|
||||
out = underlying_.format(mapper.map(item), ctx);
|
||||
out = underlying_.format(item, ctx);
|
||||
++i;
|
||||
}
|
||||
out = detail::copy<Char>(closing_bracket_, out);
|
||||
|
@ -521,13 +495,8 @@ struct formatter<
|
|||
range_format_kind<R, Char>::value != range_format::disabled &&
|
||||
range_format_kind<R, Char>::value != range_format::map &&
|
||||
range_format_kind<R, Char>::value != range_format::string &&
|
||||
range_format_kind<R, Char>::value != range_format::debug_string>
|
||||
// Workaround a bug in MSVC 2015 and earlier.
|
||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
|
||||
,
|
||||
detail::is_formattable_delayed<R, Char>
|
||||
#endif
|
||||
>::value>> {
|
||||
range_format_kind<R, Char>::value != range_format::debug_string>,
|
||||
detail::is_formattable_delayed<R, Char>>::value>> {
|
||||
private:
|
||||
using range_type = detail::maybe_const_range<R>;
|
||||
range_formatter<detail::uncvref_type<range_type>, Char> range_formatter_;
|
||||
|
@ -543,8 +512,7 @@ struct formatter<
|
|||
detail::string_literal<Char, '}'>{});
|
||||
}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return range_formatter_.parse(ctx);
|
||||
}
|
||||
|
||||
|
@ -559,7 +527,9 @@ struct formatter<
|
|||
template <typename R, typename Char>
|
||||
struct formatter<
|
||||
R, Char,
|
||||
enable_if_t<range_format_kind<R, Char>::value == range_format::map>> {
|
||||
enable_if_t<conjunction<
|
||||
bool_constant<range_format_kind<R, Char>::value == range_format::map>,
|
||||
detail::is_formattable_delayed<R, Char>>::value>> {
|
||||
private:
|
||||
using map_type = detail::maybe_const_range<R>;
|
||||
using element_type = detail::uncvref_type<map_type>;
|
||||
|
@ -571,8 +541,7 @@ struct formatter<
|
|||
public:
|
||||
FMT_CONSTEXPR formatter() {}
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
if (it != end) {
|
||||
|
@ -586,7 +555,7 @@ struct formatter<
|
|||
}
|
||||
ctx.advance_to(it);
|
||||
}
|
||||
detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
|
||||
detail::for_each(formatters_, detail::parse_empty_specs<Char>{ctx});
|
||||
return it;
|
||||
}
|
||||
|
||||
|
@ -596,12 +565,11 @@ struct formatter<
|
|||
basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
|
||||
if (!no_delimiters_) out = detail::copy<Char>(open, out);
|
||||
int i = 0;
|
||||
auto mapper = detail::range_mapper<buffered_context<Char>>();
|
||||
basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
|
||||
for (auto&& value : map) {
|
||||
if (i > 0) out = detail::copy<Char>(sep, out);
|
||||
ctx.advance_to(out);
|
||||
detail::for_each2(formatters_, mapper.map(value),
|
||||
detail::for_each2(formatters_, value,
|
||||
detail::format_tuple_element<FormatContext>{
|
||||
0, ctx, detail::string_literal<Char, ':', ' '>{}});
|
||||
++i;
|
||||
|
@ -631,8 +599,7 @@ struct formatter<
|
|||
formatter<string_type, Char> underlying_;
|
||||
|
||||
public:
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return underlying_.parse(ctx);
|
||||
}
|
||||
|
||||
|
@ -673,22 +640,22 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
|
|||
#endif
|
||||
formatter<remove_cvref_t<value_type>, Char> value_formatter_;
|
||||
|
||||
using view_ref = conditional_t<std::is_copy_constructible<It>::value,
|
||||
const join_view<It, Sentinel, Char>&,
|
||||
join_view<It, Sentinel, Char>&&>;
|
||||
using view = conditional_t<std::is_copy_constructible<It>::value,
|
||||
const join_view<It, Sentinel, Char>,
|
||||
join_view<It, Sentinel, Char>>;
|
||||
|
||||
public:
|
||||
using nonlocking = void;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return value_formatter_.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(view_ref& value, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto it = std::forward<view_ref>(value).begin;
|
||||
auto format(view& value, FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
using iter =
|
||||
conditional_t<std::is_copy_constructible<view>::value, It, It&>;
|
||||
iter it = value.begin;
|
||||
auto out = ctx.out();
|
||||
if (it == value.end) return out;
|
||||
out = value_formatter_.format(*it, ctx);
|
||||
|
@ -703,39 +670,11 @@ struct formatter<join_view<It, Sentinel, Char>, Char> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Returns a view that formats the iterator range `[begin, end)` with elements
|
||||
/// separated by `sep`.
|
||||
template <typename It, typename Sentinel>
|
||||
auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
|
||||
return {std::move(begin), end, sep};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that formats `range` with elements separated by `sep`.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* auto v = std::vector<int>{1, 2, 3};
|
||||
* fmt::print("{}", fmt::join(v, ", "));
|
||||
* // Output: 1, 2, 3
|
||||
*
|
||||
* `fmt::join` applies passed format specifiers to the range elements:
|
||||
*
|
||||
* fmt::print("{:02}", fmt::join(v, ", "));
|
||||
* // Output: 01, 02, 03
|
||||
*/
|
||||
template <typename Range>
|
||||
auto join(Range&& r, string_view sep)
|
||||
-> join_view<decltype(detail::range_begin(r)),
|
||||
decltype(detail::range_end(r))> {
|
||||
return {detail::range_begin(r), detail::range_end(r), sep};
|
||||
}
|
||||
|
||||
template <typename Char, typename... T> struct tuple_join_view : detail::view {
|
||||
const std::tuple<T...>& tuple;
|
||||
template <typename Char, typename Tuple> struct tuple_join_view : detail::view {
|
||||
const Tuple& tuple;
|
||||
basic_string_view<Char> sep;
|
||||
|
||||
tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
|
||||
tuple_join_view(const Tuple& t, basic_string_view<Char> s)
|
||||
: tuple(t), sep{s} {}
|
||||
};
|
||||
|
||||
|
@ -746,37 +685,36 @@ template <typename Char, typename... T> struct tuple_join_view : detail::view {
|
|||
# define FMT_TUPLE_JOIN_SPECIFIERS 0
|
||||
#endif
|
||||
|
||||
template <typename Char, typename... T>
|
||||
struct formatter<tuple_join_view<Char, T...>, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
|
||||
template <typename Char, typename Tuple>
|
||||
struct formatter<tuple_join_view<Char, Tuple>, 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, T...>& value,
|
||||
auto format(const tuple_join_view<Char, Tuple>& value,
|
||||
FormatContext& ctx) const -> typename FormatContext::iterator {
|
||||
return do_format(value, ctx,
|
||||
std::integral_constant<size_t, sizeof...(T)>());
|
||||
return do_format(value, ctx, std::tuple_size<Tuple>());
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
|
||||
decltype(detail::tuple::get_formatters<Tuple, Char>(
|
||||
detail::tuple_index_sequence<Tuple>())) formatters_;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
|
||||
FMT_CONSTEXPR auto do_parse(parse_context<Char>& ctx,
|
||||
std::integral_constant<size_t, 0>)
|
||||
-> decltype(ctx.begin()) {
|
||||
-> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename ParseContext, size_t N>
|
||||
FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
|
||||
template <size_t N>
|
||||
FMT_CONSTEXPR auto do_parse(parse_context<Char>& ctx,
|
||||
std::integral_constant<size_t, N>)
|
||||
-> decltype(ctx.begin()) {
|
||||
-> const Char* {
|
||||
auto end = ctx.begin();
|
||||
#if FMT_TUPLE_JOIN_SPECIFIERS
|
||||
end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
|
||||
end = std::get<std::tuple_size<Tuple>::value - N>(formatters_).parse(ctx);
|
||||
if (N > 1) {
|
||||
auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
|
||||
if (end != end1)
|
||||
|
@ -787,18 +725,20 @@ struct formatter<tuple_join_view<Char, T...>, Char> {
|
|||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
|
||||
auto do_format(const tuple_join_view<Char, Tuple>&, 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, T...>& value, FormatContext& ctx,
|
||||
auto do_format(const tuple_join_view<Char, Tuple>& value, FormatContext& ctx,
|
||||
std::integral_constant<size_t, N>) const ->
|
||||
typename FormatContext::iterator {
|
||||
auto out = std::get<sizeof...(T) - N>(formatters_)
|
||||
.format(std::get<sizeof...(T) - N>(value.tuple), ctx);
|
||||
using std::get;
|
||||
auto out =
|
||||
std::get<std::tuple_size<Tuple>::value - N>(formatters_)
|
||||
.format(get<std::tuple_size<Tuple>::value - N>(value.tuple), ctx);
|
||||
if (N <= 1) return out;
|
||||
out = detail::copy<Char>(value.sep, out);
|
||||
ctx.advance_to(out);
|
||||
|
@ -846,6 +786,34 @@ struct formatter<
|
|||
|
||||
FMT_BEGIN_EXPORT
|
||||
|
||||
/// Returns a view that formats the iterator range `[begin, end)` with elements
|
||||
/// separated by `sep`.
|
||||
template <typename It, typename Sentinel>
|
||||
auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
|
||||
return {std::move(begin), end, sep};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that formats `range` with elements separated by `sep`.
|
||||
*
|
||||
* **Example**:
|
||||
*
|
||||
* auto v = std::vector<int>{1, 2, 3};
|
||||
* fmt::print("{}", fmt::join(v, ", "));
|
||||
* // Output: 1, 2, 3
|
||||
*
|
||||
* `fmt::join` applies passed format specifiers to the range elements:
|
||||
*
|
||||
* fmt::print("{:02}", fmt::join(v, ", "));
|
||||
* // Output: 01, 02, 03
|
||||
*/
|
||||
template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
|
||||
auto join(Range&& r, string_view sep)
|
||||
-> join_view<decltype(detail::range_begin(r)),
|
||||
decltype(detail::range_end(r))> {
|
||||
return {detail::range_begin(r), detail::range_end(r), sep};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object that formats `std::tuple` with elements separated by `sep`.
|
||||
*
|
||||
|
@ -855,9 +823,9 @@ FMT_BEGIN_EXPORT
|
|||
* fmt::print("{}", fmt::join(t, ", "));
|
||||
* // Output: 1, a
|
||||
*/
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
|
||||
-> tuple_join_view<char, T...> {
|
||||
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> {
|
||||
return {tuple, sep};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# include <complex>
|
||||
# include <cstdlib>
|
||||
# include <exception>
|
||||
# include <functional>
|
||||
# include <memory>
|
||||
# include <thread>
|
||||
# include <type_traits>
|
||||
|
@ -26,7 +27,8 @@
|
|||
|
||||
// Check FMT_CPLUSPLUS to suppress a bogus warning in MSVC.
|
||||
# if FMT_CPLUSPLUS >= 201703L
|
||||
# if FMT_HAS_INCLUDE(<filesystem>)
|
||||
# if FMT_HAS_INCLUDE(<filesystem>) && \
|
||||
(!defined(FMT_CPP_LIB_FILESYSTEM) || FMT_CPP_LIB_FILESYSTEM != 0)
|
||||
# include <filesystem>
|
||||
# endif
|
||||
# if FMT_HAS_INCLUDE(<variant>)
|
||||
|
@ -122,14 +124,16 @@ template <typename Char> struct formatter<std::filesystem::path, Char> {
|
|||
public:
|
||||
FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; }
|
||||
|
||||
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) {
|
||||
auto it = ctx.begin(), end = ctx.end();
|
||||
if (it == end) return it;
|
||||
|
||||
it = detail::parse_align(it, end, specs_);
|
||||
if (it == end) return it;
|
||||
|
||||
it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx);
|
||||
Char c = *it;
|
||||
if ((c >= '0' && c <= '9') || c == '{')
|
||||
it = detail::parse_width(it, end, specs_, width_ref_, ctx);
|
||||
if (it != end && *it == '?') {
|
||||
debug_ = true;
|
||||
++it;
|
||||
|
@ -145,8 +149,8 @@ template <typename Char> struct formatter<std::filesystem::path, Char> {
|
|||
!path_type_ ? p.native()
|
||||
: p.generic_string<std::filesystem::path::value_type>();
|
||||
|
||||
detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
|
||||
ctx);
|
||||
detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
|
||||
ctx);
|
||||
if (!debug_) {
|
||||
auto s = detail::get_path_string<Char>(p, path_string);
|
||||
return detail::write(ctx.out(), basic_string_view<Char>(s), specs);
|
||||
|
@ -180,7 +184,8 @@ FMT_END_NAMESPACE
|
|||
FMT_BEGIN_NAMESPACE
|
||||
FMT_EXPORT
|
||||
template <std::size_t N, typename Char>
|
||||
struct formatter<std::bitset<N>, Char> : nested_formatter<string_view> {
|
||||
struct formatter<std::bitset<N>, Char>
|
||||
: nested_formatter<basic_string_view<Char>, Char> {
|
||||
private:
|
||||
// Functor because C++11 doesn't support generic lambdas.
|
||||
struct writer {
|
||||
|
@ -200,7 +205,7 @@ struct formatter<std::bitset<N>, Char> : nested_formatter<string_view> {
|
|||
template <typename FormatContext>
|
||||
auto format(const std::bitset<N>& bs, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return write_padded(ctx, writer{bs});
|
||||
return this->write_padded(ctx, writer{bs});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -233,7 +238,7 @@ struct formatter<std::optional<T>, Char,
|
|||
FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
|
||||
|
||||
public:
|
||||
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) {
|
||||
maybe_set_debug_format(underlying_, true);
|
||||
return underlying_.parse(ctx);
|
||||
}
|
||||
|
@ -277,10 +282,10 @@ FMT_BEGIN_NAMESPACE
|
|||
FMT_EXPORT
|
||||
template <typename T, typename E, typename Char>
|
||||
struct formatter<std::expected<T, E>, Char,
|
||||
std::enable_if_t<is_formattable<T, Char>::value &&
|
||||
std::enable_if_t<(std::is_void<T>::value ||
|
||||
is_formattable<T, Char>::value) &&
|
||||
is_formattable<E, Char>::value>> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
|
@ -291,7 +296,8 @@ struct formatter<std::expected<T, E>, Char,
|
|||
|
||||
if (value.has_value()) {
|
||||
out = detail::write<Char>(out, "expected(");
|
||||
out = detail::write_escaped_alternative<Char>(out, *value);
|
||||
if constexpr (!std::is_void<T>::value)
|
||||
out = detail::write_escaped_alternative<Char>(out, *value);
|
||||
} else {
|
||||
out = detail::write<Char>(out, "unexpected(");
|
||||
out = detail::write_escaped_alternative<Char>(out, value.error());
|
||||
|
@ -307,9 +313,7 @@ FMT_END_NAMESPACE
|
|||
FMT_BEGIN_NAMESPACE
|
||||
FMT_EXPORT
|
||||
template <> struct formatter<std::source_location> {
|
||||
template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
|
||||
return ctx.begin();
|
||||
}
|
||||
FMT_CONSTEXPR auto parse(parse_context<>& ctx) { return ctx.begin(); }
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::source_location& loc, FormatContext& ctx) const
|
||||
|
@ -365,8 +369,7 @@ template <typename T, typename C> struct is_variant_formattable {
|
|||
|
||||
FMT_EXPORT
|
||||
template <typename Char> struct formatter<std::monostate, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
|
@ -383,8 +386,7 @@ struct formatter<
|
|||
Variant, Char,
|
||||
std::enable_if_t<std::conjunction_v<
|
||||
is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
|
@ -413,20 +415,37 @@ FMT_END_NAMESPACE
|
|||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
FMT_EXPORT
|
||||
template <typename Char> struct formatter<std::error_code, Char> {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
template <> struct formatter<std::error_code> {
|
||||
private:
|
||||
format_specs specs_;
|
||||
detail::arg_ref<char> width_ref_;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* {
|
||||
auto it = ctx.begin(), end = ctx.end();
|
||||
if (it == end) return it;
|
||||
|
||||
it = detail::parse_align(it, end, specs_);
|
||||
if (it == end) return it;
|
||||
|
||||
char c = *it;
|
||||
if ((c >= '0' && c <= '9') || c == '{')
|
||||
it = detail::parse_width(it, end, specs_, width_ref_, ctx);
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
out = detail::write_bytes<Char>(out, ec.category().name(), format_specs());
|
||||
out = detail::write<Char>(out, Char(':'));
|
||||
out = detail::write<Char>(out, ec.value());
|
||||
return out;
|
||||
FMT_CONSTEXPR20 auto format(const std::error_code& ec,
|
||||
FormatContext& ctx) const -> decltype(ctx.out()) {
|
||||
auto specs = specs_;
|
||||
detail::handle_dynamic_spec(specs.dynamic_width(), specs.width, width_ref_,
|
||||
ctx);
|
||||
memory_buffer buf;
|
||||
buf.append(string_view(ec.category().name()));
|
||||
buf.push_back(':');
|
||||
detail::write<char>(appender(buf), ec.value());
|
||||
return detail::write<char>(ctx.out(), string_view(buf.data(), buf.size()),
|
||||
specs);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -506,8 +525,7 @@ template <typename Char>
|
|||
struct formatter<std::type_info, Char // DEPRECATED! Mixing code unit types.
|
||||
> {
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
|
@ -528,8 +546,7 @@ struct formatter<
|
|||
bool with_typename_ = false;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
if (it == end || *it == '}') return it;
|
||||
|
@ -643,7 +660,7 @@ template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
|||
if (c.real() != 0) {
|
||||
*out++ = Char('(');
|
||||
out = detail::write<Char>(out, c.real(), specs, ctx.locale());
|
||||
specs.sign = sign::plus;
|
||||
specs.set_sign(sign::plus);
|
||||
out = detail::write<Char>(out, c.imag(), specs, ctx.locale());
|
||||
if (!detail::isfinite(c.imag())) *out++ = Char(' ');
|
||||
*out++ = Char('i');
|
||||
|
@ -657,8 +674,7 @@ template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
|||
}
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
|
||||
if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
|
||||
return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
|
||||
detail::type_constant<T, Char>::value);
|
||||
|
@ -668,12 +684,11 @@ template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
|||
auto format(const std::complex<T>& c, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
auto specs = specs_;
|
||||
if (specs.width_ref.kind != detail::arg_id_kind::none ||
|
||||
specs.precision_ref.kind != detail::arg_id_kind::none) {
|
||||
detail::handle_dynamic_spec<detail::width_checker>(specs.width,
|
||||
specs.width_ref, ctx);
|
||||
detail::handle_dynamic_spec<detail::precision_checker>(
|
||||
specs.precision, specs.precision_ref, ctx);
|
||||
if (specs.dynamic()) {
|
||||
detail::handle_dynamic_spec(specs.dynamic_width(), specs.width,
|
||||
specs.width_ref, ctx);
|
||||
detail::handle_dynamic_spec(specs.dynamic_precision(), specs.precision,
|
||||
specs.precision_ref, ctx);
|
||||
}
|
||||
|
||||
if (specs.width == 0) return do_format(c, specs, ctx, ctx.out());
|
||||
|
@ -681,12 +696,12 @@ template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
|||
|
||||
auto outer_specs = format_specs();
|
||||
outer_specs.width = specs.width;
|
||||
outer_specs.fill = specs.fill;
|
||||
outer_specs.align = specs.align;
|
||||
outer_specs.copy_fill_from(specs);
|
||||
outer_specs.set_align(specs.align());
|
||||
|
||||
specs.width = 0;
|
||||
specs.fill = {};
|
||||
specs.align = align::none;
|
||||
specs.set_fill({});
|
||||
specs.set_align(align::none);
|
||||
|
||||
do_format(c, specs, ctx, basic_appender<Char>(buf));
|
||||
return detail::write<Char>(ctx.out(),
|
||||
|
@ -695,5 +710,17 @@ template <typename T, typename Char> struct formatter<std::complex<T>, Char> {
|
|||
}
|
||||
};
|
||||
|
||||
FMT_EXPORT
|
||||
template <typename T, typename Char>
|
||||
struct formatter<std::reference_wrapper<T>, Char,
|
||||
enable_if_t<is_formattable<remove_cvref_t<T>, Char>::value>>
|
||||
: formatter<remove_cvref_t<T>, Char> {
|
||||
template <typename FormatContext>
|
||||
auto format(std::reference_wrapper<T> ref, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return formatter<remove_cvref_t<T>, Char>::format(ref.get(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
#endif // FMT_STD_H_
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
|
||||
#include "color.h"
|
||||
#include "format.h"
|
||||
#include "ostream.h"
|
||||
#include "ranges.h"
|
||||
|
||||
#ifndef FMT_MODULE
|
||||
# include <cwchar>
|
||||
# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||
# if FMT_USE_LOCALE
|
||||
# include <locale>
|
||||
# endif
|
||||
#endif
|
||||
|
@ -34,7 +35,8 @@ struct format_string_char<
|
|||
};
|
||||
|
||||
template <typename S>
|
||||
struct format_string_char<S, enable_if_t<is_compile_string<S>::value>> {
|
||||
struct format_string_char<
|
||||
S, enable_if_t<std::is_base_of<detail::compile_string, S>::value>> {
|
||||
using type = typename S::char_type;
|
||||
};
|
||||
|
||||
|
@ -43,7 +45,7 @@ using format_string_char_t = typename format_string_char<S>::type;
|
|||
|
||||
inline auto write_loc(basic_appender<wchar_t> out, loc_value value,
|
||||
const format_specs& specs, locale_ref loc) -> bool {
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
#if FMT_USE_LOCALE
|
||||
auto& numpunct =
|
||||
std::use_facet<std::numpunct<wchar_t>>(loc.get<std::locale>());
|
||||
auto separator = std::wstring();
|
||||
|
@ -58,30 +60,64 @@ inline auto write_loc(basic_appender<wchar_t> out, loc_value value,
|
|||
FMT_BEGIN_EXPORT
|
||||
|
||||
using wstring_view = basic_string_view<wchar_t>;
|
||||
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
||||
using wformat_parse_context = parse_context<wchar_t>;
|
||||
using wformat_context = buffered_context<wchar_t>;
|
||||
using wformat_args = basic_format_args<wformat_context>;
|
||||
using wmemory_buffer = basic_memory_buffer<wchar_t>;
|
||||
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
// Workaround broken conversion on older gcc.
|
||||
template <typename... Args> using wformat_string = wstring_view;
|
||||
inline auto runtime(wstring_view s) -> wstring_view { return s; }
|
||||
#else
|
||||
template <typename... Args>
|
||||
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
|
||||
template <typename Char, typename... T> struct basic_fstring {
|
||||
private:
|
||||
basic_string_view<Char> str_;
|
||||
|
||||
static constexpr int num_static_named_args =
|
||||
detail::count_static_named_args<T...>();
|
||||
|
||||
using checker = detail::format_string_checker<
|
||||
Char, static_cast<int>(sizeof...(T)), num_static_named_args,
|
||||
num_static_named_args != detail::count_named_args<T...>()>;
|
||||
|
||||
using arg_pack = detail::arg_pack<T...>;
|
||||
|
||||
public:
|
||||
using t = basic_fstring;
|
||||
|
||||
template <typename S,
|
||||
FMT_ENABLE_IF(
|
||||
std::is_convertible<const S&, basic_string_view<Char>>::value)>
|
||||
FMT_CONSTEVAL FMT_ALWAYS_INLINE basic_fstring(const S& s) : str_(s) {
|
||||
if (FMT_USE_CONSTEVAL)
|
||||
detail::parse_format_string<Char>(s, checker(s, arg_pack()));
|
||||
}
|
||||
template <typename S,
|
||||
FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
|
||||
std::is_same<typename S::char_type, Char>::value)>
|
||||
FMT_ALWAYS_INLINE basic_fstring(const S&) : str_(S()) {
|
||||
FMT_CONSTEXPR auto sv = basic_string_view<Char>(S());
|
||||
FMT_CONSTEXPR int ignore =
|
||||
(parse_format_string(sv, checker(sv, arg_pack())), 0);
|
||||
detail::ignore_unused(ignore);
|
||||
}
|
||||
basic_fstring(runtime_format_string<Char> fmt) : str_(fmt.str) {}
|
||||
|
||||
operator basic_string_view<Char>() const { return str_; }
|
||||
auto get() const -> basic_string_view<Char> { return str_; }
|
||||
};
|
||||
|
||||
template <typename Char, typename... T>
|
||||
using basic_format_string = basic_fstring<Char, T...>;
|
||||
|
||||
template <typename... T>
|
||||
using wformat_string = typename basic_format_string<wchar_t, T...>::t;
|
||||
inline auto runtime(wstring_view s) -> runtime_format_string<wchar_t> {
|
||||
return {{s}};
|
||||
}
|
||||
#endif
|
||||
|
||||
template <> struct is_char<wchar_t> : std::true_type {};
|
||||
template <> struct is_char<char16_t> : std::true_type {};
|
||||
template <> struct is_char<char32_t> : std::true_type {};
|
||||
|
||||
#ifdef __cpp_char8_t
|
||||
template <>
|
||||
struct is_char<char8_t> : bool_constant<detail::is_utf8_enabled()> {};
|
||||
template <> struct is_char<char8_t> : bool_constant<detail::is_utf8_enabled> {};
|
||||
#endif
|
||||
|
||||
template <typename... T>
|
||||
|
@ -90,14 +126,13 @@ constexpr auto make_wformat_args(T&... args)
|
|||
return fmt::make_format_args<wformat_context>(args...);
|
||||
}
|
||||
|
||||
#if !FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
inline namespace literals {
|
||||
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
|
||||
constexpr auto operator""_a(const wchar_t* s, size_t)
|
||||
-> detail::udl_arg<wchar_t> {
|
||||
inline auto operator""_a(const wchar_t* s, size_t) -> detail::udl_arg<wchar_t> {
|
||||
return {s};
|
||||
}
|
||||
#endif
|
||||
} // namespace literals
|
||||
#endif
|
||||
|
||||
template <typename It, typename Sentinel>
|
||||
auto join(It begin, Sentinel end, wstring_view sep)
|
||||
|
@ -105,9 +140,9 @@ auto join(It begin, Sentinel end, wstring_view sep)
|
|||
return {begin, end, sep};
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
template <typename Range, FMT_ENABLE_IF(!is_tuple_like<Range>::value)>
|
||||
auto join(Range&& range, wstring_view sep)
|
||||
-> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,
|
||||
-> join_view<decltype(std::begin(range)), decltype(std::end(range)),
|
||||
wchar_t> {
|
||||
return join(std::begin(range), std::end(range), sep);
|
||||
}
|
||||
|
@ -118,19 +153,19 @@ auto join(std::initializer_list<T> list, wstring_view sep)
|
|||
return join(std::begin(list), std::end(list), sep);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
auto join(const std::tuple<T...>& tuple, basic_string_view<wchar_t> sep)
|
||||
-> tuple_join_view<wchar_t, T...> {
|
||||
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> {
|
||||
return {tuple, sep};
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
auto vformat(basic_string_view<Char> format_str,
|
||||
auto vformat(basic_string_view<Char> fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> std::basic_string<Char> {
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
return to_string(buf);
|
||||
detail::vformat_to(buf, fmt, args);
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
|
@ -151,8 +186,8 @@ template <typename S, typename... T,
|
|||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
|
||||
!std::is_same<Char, wchar_t>::value)>
|
||||
auto format(const S& format_str, T&&... args) -> std::basic_string<Char> {
|
||||
return vformat(detail::to_string_view(format_str),
|
||||
auto format(const S& fmt, T&&... args) -> std::basic_string<Char> {
|
||||
return vformat(detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
|
@ -160,31 +195,33 @@ 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& format_str,
|
||||
inline auto vformat(const Locale& loc, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> std::basic_string<Char> {
|
||||
return detail::vformat(loc, detail::to_string_view(format_str), args);
|
||||
auto buf = basic_memory_buffer<Char>();
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt), args,
|
||||
detail::locale_ref(loc));
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
template <typename Locale, 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& format_str, T&&... args)
|
||||
inline auto format(const Locale& loc, const S& fmt, T&&... args)
|
||||
-> std::basic_string<Char> {
|
||||
return detail::vformat(
|
||||
loc, detail::to_string_view(format_str),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
return vformat(loc, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S,
|
||||
typename Char = detail::format_string_char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
|
||||
detail::is_exotic_char<Char>::value)>
|
||||
auto vformat_to(OutputIt out, const S& format_str,
|
||||
auto vformat_to(OutputIt out, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args) -> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
detail::vformat_to(buf, detail::to_string_view(format_str), args);
|
||||
detail::vformat_to(buf, detail::to_string_view(fmt), args);
|
||||
return detail::get_iterator(buf, out);
|
||||
}
|
||||
|
||||
|
@ -203,37 +240,35 @@ template <typename Locale, typename S, typename OutputIt, typename... Args,
|
|||
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& format_str,
|
||||
inline auto vformat_to(OutputIt out, const Locale& loc, const S& fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> OutputIt {
|
||||
auto&& buf = detail::get_buffer<Char>(out);
|
||||
vformat_to(buf, detail::to_string_view(format_str), args,
|
||||
detail::locale_ref(loc));
|
||||
vformat_to(buf, detail::to_string_view(fmt), args, detail::locale_ref(loc));
|
||||
return detail::get_iterator(buf, out);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Locale, typename S, typename... T,
|
||||
template <typename Locale, 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& format_str,
|
||||
inline auto format_to(OutputIt out, const Locale& loc, const S& fmt,
|
||||
T&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
return vformat_to(out, loc, detail::to_string_view(format_str),
|
||||
return vformat_to(out, loc, detail::to_string_view(fmt),
|
||||
fmt::make_format_args<buffered_context<Char>>(args...));
|
||||
}
|
||||
|
||||
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> format_str,
|
||||
inline auto vformat_to_n(OutputIt out, size_t n, basic_string_view<Char> fmt,
|
||||
typename detail::vformat_args<Char>::type args)
|
||||
-> format_to_n_result<OutputIt> {
|
||||
using traits = detail::fixed_buffer_traits;
|
||||
auto buf = detail::iterator_buffer<OutputIt, Char, traits>(out, n);
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
detail::vformat_to(buf, fmt, args);
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
|
@ -291,7 +326,7 @@ inline auto vformat(const text_style& ts, wstring_view fmt, wformat_args args)
|
|||
-> std::wstring {
|
||||
auto buf = wmemory_buffer();
|
||||
detail::vformat_to(buf, ts, fmt, args);
|
||||
return fmt::to_string(buf);
|
||||
return {buf.data(), buf.size()};
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
|
@ -312,6 +347,22 @@ FMT_DEPRECATED void print(const text_style& ts, wformat_string<T...> fmt,
|
|||
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);
|
||||
detail::write_buffer(os, buffer);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void print(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
|
||||
vprint(os, fmt, fmt::make_format_args<buffered_context<wchar_t>>(args...));
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
void println(std::wostream& os, wformat_string<T...> fmt, T&&... args) {
|
||||
print(os, L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
|
||||
}
|
||||
|
||||
/// Converts `value` to `std::wstring` using the default format for type `T`.
|
||||
template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
|
||||
return format(FMT_STRING(L"{}"), value);
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
module;
|
||||
|
||||
#define FMT_MODULE
|
||||
|
||||
#ifdef _MSVC_LANG
|
||||
# define FMT_CPLUSPLUS _MSVC_LANG
|
||||
#else
|
||||
# define FMT_CPLUSPLUS __cplusplus
|
||||
#endif
|
||||
|
||||
// Put all implementation-provided headers into the global module fragment
|
||||
// to prevent attachment to this module.
|
||||
#ifndef FMT_IMPORT_STD
|
||||
|
@ -15,7 +23,9 @@ module;
|
|||
# include <cstring>
|
||||
# include <ctime>
|
||||
# include <exception>
|
||||
# include <expected>
|
||||
# if FMT_CPLUSPLUS > 202002L
|
||||
# include <expected>
|
||||
# endif
|
||||
# include <filesystem>
|
||||
# include <fstream>
|
||||
# include <functional>
|
||||
|
@ -127,9 +137,17 @@ extern "C++" {
|
|||
module :private;
|
||||
#endif
|
||||
|
||||
#ifdef FMT_ATTACH_TO_GLOBAL_MODULE
|
||||
extern "C++" {
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_INCLUDE("format.cc")
|
||||
# include "format.cc"
|
||||
#endif
|
||||
#if FMT_OS && FMT_HAS_INCLUDE("os.cc")
|
||||
# include "os.cc"
|
||||
#endif
|
||||
|
||||
#ifdef FMT_ATTACH_TO_GLOBAL_MODULE
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,8 @@ template FMT_API auto dragonbox::to_decimal(float x) noexcept
|
|||
template FMT_API auto dragonbox::to_decimal(double x) noexcept
|
||||
-> dragonbox::decimal_fp<double>;
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
#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
|
||||
|
@ -26,8 +27,10 @@ template FMT_API auto thousands_sep_impl(locale_ref)
|
|||
-> thousands_sep_result<char>;
|
||||
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);
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
|||
}
|
||||
|
||||
void report_windows_error(int error_code, const char* message) noexcept {
|
||||
report_error(detail::format_windows_error, error_code, message);
|
||||
do_report_error(detail::format_windows_error, error_code, message);
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
|
@ -374,30 +374,25 @@ long getpagesize() {
|
|||
}
|
||||
# endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
void file_buffer::grow(buffer<char>& buf, size_t) {
|
||||
if (buf.size() == buf.capacity()) static_cast<file_buffer&>(buf).flush();
|
||||
void ostream::grow(buffer<char>& buf, size_t) {
|
||||
if (buf.size() == buf.capacity()) static_cast<ostream&>(buf).flush();
|
||||
}
|
||||
|
||||
file_buffer::file_buffer(cstring_view path, const ostream_params& params)
|
||||
ostream::ostream(cstring_view path, const detail::ostream_params& params)
|
||||
: buffer<char>(grow), file_(path, params.oflag) {
|
||||
set(new char[params.buffer_size], params.buffer_size);
|
||||
}
|
||||
|
||||
file_buffer::file_buffer(file_buffer&& other) noexcept
|
||||
ostream::ostream(ostream&& other) noexcept
|
||||
: buffer<char>(grow, other.data(), other.size(), other.capacity()),
|
||||
file_(std::move(other.file_)) {
|
||||
other.clear();
|
||||
other.set(nullptr, 0);
|
||||
}
|
||||
|
||||
file_buffer::~file_buffer() {
|
||||
ostream::~ostream() {
|
||||
flush();
|
||||
delete[] data();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
ostream::~ostream() = default;
|
||||
#endif // FMT_USE_FCNTL
|
||||
FMT_END_NAMESPACE
|
||||
|
|
|
@ -29,3 +29,5 @@
|
|||
#define ICON_EMOJI_UNLOCKED "\xf0\x9f\x94\x93"
|
||||
#define ICON_EMOJI_REFRESH "\xf0\x9f\x94\x84"
|
||||
#define ICON_EMOJI_PROHIBITED "\xf0\x9f\x9a\xab"
|
||||
#define ICON_EMOJI_CALENDAR "\xF0\x9F\x93\x85"
|
||||
#define ICON_EMOJI_HOURGLASS "\xe2\x8f\xb3"
|
||||
|
|
|
@ -10957,7 +10957,7 @@ void ImGui::SetScrollY(float scroll_y)
|
|||
void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio)
|
||||
{
|
||||
IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
|
||||
window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 + window->Scroll.x); // Convert local position to scroll offset
|
||||
window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 + window->ScrollExpected.x); // Convert local position to scroll offset
|
||||
window->ScrollTargetCenterRatio.x = center_x_ratio;
|
||||
window->ScrollTargetEdgeSnapDist.x = 0.0f;
|
||||
}
|
||||
|
@ -10965,7 +10965,7 @@ void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x
|
|||
void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio)
|
||||
{
|
||||
IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
|
||||
window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 + window->Scroll.y); // Convert local position to scroll offset
|
||||
window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 + window->ScrollExpected.y); // Convert local position to scroll offset
|
||||
window->ScrollTargetCenterRatio.y = center_y_ratio;
|
||||
window->ScrollTargetEdgeSnapDist.y = 0.0f;
|
||||
}
|
||||
|
@ -12959,6 +12959,7 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
|||
bb_rel.TranslateX(-bb_rel.GetWidth()); // Previous column
|
||||
clip_dir = ImGuiDir_Left;
|
||||
}
|
||||
SetScrollY(window, window->ScrollMax.y);
|
||||
do_forward = true;
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
|
@ -12969,6 +12970,7 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
|||
bb_rel.TranslateX(+bb_rel.GetWidth()); // Next column
|
||||
clip_dir = ImGuiDir_Right;
|
||||
}
|
||||
SetScrollY(window, 0.0f);
|
||||
do_forward = true;
|
||||
}
|
||||
if (!do_forward)
|
||||
|
|
|
@ -225,6 +225,42 @@ RC_EXPORT int RC_CCONV rc_api_init_fetch_game_titles_request(rc_api_request_t* r
|
|||
RC_EXPORT int RC_CCONV rc_api_process_fetch_game_titles_server_response(rc_api_fetch_game_titles_response_t* response, const rc_api_server_response_t* server_response);
|
||||
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_game_titles_response(rc_api_fetch_game_titles_response_t* response);
|
||||
|
||||
/* --- Fetch Game Hashes --- */
|
||||
|
||||
/**
|
||||
* API parameters for a fetch games list request.
|
||||
*/
|
||||
typedef struct rc_api_fetch_hash_library_request_t {
|
||||
/* The unique identifier of the console to query */
|
||||
uint32_t console_id;
|
||||
} rc_api_fetch_hash_library_request_t;
|
||||
|
||||
/* A hash library entry */
|
||||
typedef struct rc_api_hash_library_entry_t {
|
||||
/* The hash for the game */
|
||||
const char* hash;
|
||||
/* The unique identifier of the game */
|
||||
uint32_t game_id;
|
||||
} rc_api_hash_library_entry_t;
|
||||
|
||||
/**
|
||||
* Response data for a fetch hash library request.
|
||||
*/
|
||||
typedef struct rc_api_fetch_hash_library_response_t {
|
||||
/* An array of entries, one per game */
|
||||
rc_api_hash_library_entry_t* entries;
|
||||
/* The number of items in the entries array */
|
||||
uint32_t num_entries;
|
||||
|
||||
/* Common server-provided response information */
|
||||
rc_api_response_t response;
|
||||
}
|
||||
rc_api_fetch_hash_library_response_t;
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_api_init_fetch_hash_library_request(rc_api_request_t* request, const rc_api_fetch_hash_library_request_t* api_params);
|
||||
RC_EXPORT int RC_CCONV rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_response_t* response, const rc_api_server_response_t* server_response);
|
||||
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_hash_library_response(rc_api_fetch_hash_library_response_t* response);
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_API_INFO_H */
|
||||
|
|
|
@ -147,6 +147,49 @@ RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_response(rc_api_fetch_u
|
|||
RC_EXPORT int RC_CCONV rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_response_t* response, const rc_api_server_response_t* server_response);
|
||||
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response);
|
||||
|
||||
/* --- Fetch All Progress --- */
|
||||
|
||||
/**
|
||||
* API parameters for a fetch all progress request.
|
||||
*/
|
||||
typedef struct rc_api_fetch_all_progress_request_t {
|
||||
/* The username of the player */
|
||||
const char* username;
|
||||
/* The API token from the login request */
|
||||
const char* api_token;
|
||||
/* The unique identifier of the console to query */
|
||||
uint32_t console_id;
|
||||
} rc_api_fetch_all_progress_request_t;
|
||||
|
||||
/* An all-progress entry */
|
||||
typedef struct rc_api_all_progress_entry_t {
|
||||
/* The unique identifier of the game */
|
||||
uint32_t game_id;
|
||||
/* The total number of achievements for this game */
|
||||
uint32_t num_achievements;
|
||||
/* The total number of unlocked achievements for this game in softcore mode */
|
||||
uint32_t num_unlocked_achievements;
|
||||
/* The total number of unlocked achievements for this game in hardcore mode */
|
||||
uint32_t num_unlocked_achievements_hardcore;
|
||||
} rc_api_all_progress_entry_t;
|
||||
|
||||
/**
|
||||
* Response data for a fetch all progress request.
|
||||
*/
|
||||
typedef struct rc_api_fetch_all_progress_response_t {
|
||||
/* An array of entries, one per game */
|
||||
rc_api_all_progress_entry_t* entries;
|
||||
/* The number of items in the entries array */
|
||||
uint32_t num_entries;
|
||||
|
||||
/* Common server-provided response information */
|
||||
rc_api_response_t response;
|
||||
} rc_api_fetch_all_progress_response_t;
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_api_init_fetch_all_progress_request(rc_api_request_t* request, const rc_api_fetch_all_progress_request_t* api_params);
|
||||
RC_EXPORT int RC_CCONV rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_response_t* response, const rc_api_server_response_t* server_response);
|
||||
RC_EXPORT void RC_CCONV rc_api_destroy_fetch_all_progress_response(rc_api_fetch_all_progress_response_t* response);
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
#endif /* RC_API_H */
|
||||
|
|
|
@ -141,6 +141,11 @@ RC_EXPORT void RC_CCONV rc_client_abort_async(rc_client_t* client, rc_client_asy
|
|||
*/
|
||||
RC_EXPORT size_t RC_CCONV rc_client_get_user_agent_clause(rc_client_t* client, char buffer[], size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Returns true if any achievement submissions have failed and are currently pending.
|
||||
*/
|
||||
RC_EXPORT int RC_CCONV rc_client_is_disconnected(rc_client_t* client);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Logging |
|
||||
\*****************************************************************************/
|
||||
|
@ -310,6 +315,88 @@ typedef struct rc_client_subset_t {
|
|||
|
||||
RC_EXPORT const rc_client_subset_t* RC_CCONV rc_client_get_subset_info(rc_client_t* client, uint32_t subset_id);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Game Info |
|
||||
\*****************************************************************************/
|
||||
|
||||
typedef struct rc_client_hash_library_entry_t
|
||||
{
|
||||
/* The hash for the game */
|
||||
const char* hash;
|
||||
/* The unique identifier of the game */
|
||||
uint32_t game_id;
|
||||
} rc_client_hash_library_entry_t;
|
||||
|
||||
typedef struct rc_client_hash_library_t
|
||||
{
|
||||
/* An array of entries, one per game */
|
||||
rc_client_hash_library_entry_t* entries;
|
||||
/* The number of items in the entries array */
|
||||
uint32_t num_entries;
|
||||
} rc_client_hash_library_t;
|
||||
|
||||
/**
|
||||
* Callback that is fired when a hash library request completes. list may be null if the query failed.
|
||||
*/
|
||||
typedef void(RC_CCONV* rc_client_fetch_hash_library_callback_t)(int result, const char* error_message,
|
||||
rc_client_hash_library_t* list, rc_client_t* client,
|
||||
void* callback_userdata);
|
||||
|
||||
/**
|
||||
* Starts an asynchronous request for all hashes for the given console.
|
||||
* This request returns a mapping from hashes to the game's unique identifier. A single game may have multiple
|
||||
* hashes in the case of multi-disc games, or variants that are still compatible with the same achievement set.
|
||||
*/
|
||||
RC_EXPORT rc_client_async_handle_t* RC_CCONV rc_client_begin_fetch_hash_library(
|
||||
rc_client_t* client, uint32_t console_id, rc_client_fetch_hash_library_callback_t callback, void* callback_userdata);
|
||||
|
||||
|
||||
/**
|
||||
* Destroys a previously-allocated result from the rc_client_destroy_hash_library() callback.
|
||||
*/
|
||||
RC_EXPORT void RC_CCONV rc_client_destroy_hash_library(rc_client_hash_library_t* list);
|
||||
|
||||
typedef struct rc_client_all_progress_list_entry_t
|
||||
{
|
||||
/* The unique identifier of the game */
|
||||
uint32_t game_id;
|
||||
/* The total number of achievements for this game */
|
||||
uint32_t num_achievements;
|
||||
/* The total number of unlocked achievements for this game in softcore mode */
|
||||
uint32_t num_unlocked_achievements;
|
||||
/* The total number of unlocked achievements for this game in hardcore mode */
|
||||
uint32_t num_unlocked_achievements_hardcore;
|
||||
} rc_client_all_progress_list_entry_t;
|
||||
|
||||
typedef struct rc_client_all_progress_list_t
|
||||
{
|
||||
/* An array of entries, one per game */
|
||||
rc_client_all_progress_list_entry_t* entries;
|
||||
/* The number of items in the entries array */
|
||||
uint32_t num_entries;
|
||||
} rc_client_all_progress_list_t;
|
||||
|
||||
/**
|
||||
* Callback that is fired when an all progress query completes. list may be null if the query failed.
|
||||
*/
|
||||
typedef void(RC_CCONV* rc_client_fetch_all_progress_list_callback_t)(int result, const char* error_message,
|
||||
rc_client_all_progress_list_t* list,
|
||||
rc_client_t* client, void* callback_userdata);
|
||||
|
||||
/**
|
||||
* Starts an asynchronous request for all progress for the given console.
|
||||
* This query returns the total number of achievements for all games tracked by this console, as well as
|
||||
* the user's achievement unlock count for both softcore and hardcore modes.
|
||||
*/
|
||||
RC_EXPORT rc_client_async_handle_t* RC_CCONV
|
||||
rc_client_begin_fetch_all_progress_list(rc_client_t* client, uint32_t console_id,
|
||||
rc_client_fetch_all_progress_list_callback_t callback, void* callback_userdata);
|
||||
|
||||
/**
|
||||
* Destroys a previously-allocated result from the rc_client_begin_fetch_all_progress_list() callback.
|
||||
*/
|
||||
RC_EXPORT void RC_CCONV rc_client_destroy_all_progress_list(rc_client_all_progress_list_t* list);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Achievements |
|
||||
\*****************************************************************************/
|
||||
|
@ -421,6 +508,11 @@ RC_EXPORT void RC_CCONV rc_client_destroy_achievement_list(rc_client_achievement
|
|||
*/
|
||||
RC_EXPORT int RC_CCONV rc_client_has_achievements(rc_client_t* client);
|
||||
|
||||
/**
|
||||
* Returns the number of outstanding achievement unlocks.
|
||||
*/
|
||||
RC_EXPORT int RC_CCONV rc_client_get_award_achievement_pending_count(rc_client_t* client);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Leaderboards |
|
||||
\*****************************************************************************/
|
||||
|
@ -504,7 +596,7 @@ RC_EXPORT void RC_CCONV rc_client_destroy_leaderboard_list(rc_client_leaderboard
|
|||
/**
|
||||
* Returns non-zero if the current game has any leaderboards.
|
||||
*/
|
||||
RC_EXPORT int RC_CCONV rc_client_has_leaderboards(rc_client_t* client);
|
||||
RC_EXPORT int RC_CCONV rc_client_has_leaderboards(rc_client_t* client, int include_hidden);
|
||||
|
||||
typedef struct rc_client_leaderboard_entry_t {
|
||||
const char* user;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "rc_api_info.h"
|
||||
#include "rc_api_common.h"
|
||||
|
||||
#include "rc_consoles.h"
|
||||
#include "rc_runtime_types.h"
|
||||
|
||||
#include "../rc_compat.h"
|
||||
|
@ -464,3 +465,87 @@ int rc_api_process_fetch_game_titles_server_response(rc_api_fetch_game_titles_re
|
|||
void rc_api_destroy_fetch_game_titles_response(rc_api_fetch_game_titles_response_t* response) {
|
||||
rc_buffer_destroy(&response->response.buffer);
|
||||
}
|
||||
|
||||
/* --- Fetch Game Hashes --- */
|
||||
|
||||
int rc_api_init_fetch_hash_library_request(rc_api_request_t* request,
|
||||
const rc_api_fetch_hash_library_request_t* api_params)
|
||||
{
|
||||
rc_api_url_builder_t builder;
|
||||
rc_api_url_build_dorequest_url(request);
|
||||
|
||||
if (api_params->console_id == RC_CONSOLE_UNKNOWN)
|
||||
return RC_INVALID_STATE;
|
||||
|
||||
rc_url_builder_init(&builder, &request->buffer, 48);
|
||||
rc_url_builder_append_str_param(&builder, "r", "hashlibrary");
|
||||
rc_url_builder_append_unum_param(&builder, "c", api_params->console_id);
|
||||
|
||||
request->post_data = rc_url_builder_finalize(&builder);
|
||||
request->content_type = RC_CONTENT_TYPE_URLENCODED;
|
||||
|
||||
return builder.result;
|
||||
}
|
||||
|
||||
int rc_api_process_fetch_hash_library_server_response(rc_api_fetch_hash_library_response_t* response,
|
||||
const rc_api_server_response_t* server_response)
|
||||
{
|
||||
rc_api_hash_library_entry_t* entry;
|
||||
rc_json_iterator_t iterator;
|
||||
rc_json_field_t field;
|
||||
int result;
|
||||
char* end;
|
||||
|
||||
rc_json_field_t fields[] = {
|
||||
RC_JSON_NEW_FIELD("Success"),
|
||||
RC_JSON_NEW_FIELD("Error"),
|
||||
RC_JSON_NEW_FIELD("MD5List"),
|
||||
};
|
||||
|
||||
memset(response, 0, sizeof(*response));
|
||||
rc_buffer_init(&response->response.buffer);
|
||||
|
||||
result =
|
||||
rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
|
||||
if (result != RC_OK)
|
||||
return result;
|
||||
|
||||
if (!fields[2].value_start)
|
||||
{
|
||||
/* call rc_json_get_required_object to generate the error message */
|
||||
rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "MD5List");
|
||||
return RC_MISSING_VALUE;
|
||||
}
|
||||
|
||||
response->num_entries = fields[2].array_size;
|
||||
rc_buffer_reserve(&response->response.buffer, response->num_entries * (32 + sizeof(rc_api_hash_library_entry_t)));
|
||||
|
||||
response->entries = (rc_api_hash_library_entry_t*)rc_buffer_alloc(
|
||||
&response->response.buffer, response->num_entries * sizeof(rc_api_hash_library_entry_t));
|
||||
if (!response->entries)
|
||||
return RC_OUT_OF_MEMORY;
|
||||
|
||||
memset(&iterator, 0, sizeof(iterator));
|
||||
iterator.json = fields[2].value_start;
|
||||
iterator.end = fields[2].value_end;
|
||||
|
||||
entry = response->entries;
|
||||
while (rc_json_get_next_object_field(&iterator, &field))
|
||||
{
|
||||
/* TODO: This isn't handling escape characters in the key, the RC JSON parsing functions have no method for it. */
|
||||
entry->hash = rc_buffer_strncpy(&response->response.buffer, field.name, field.name_len);
|
||||
|
||||
field.name = "";
|
||||
if (!rc_json_get_unum(&entry->game_id, &field, ""))
|
||||
return RC_MISSING_VALUE;
|
||||
|
||||
++entry;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
void rc_api_destroy_fetch_hash_library_response(rc_api_fetch_hash_library_response_t* response)
|
||||
{
|
||||
rc_buffer_destroy(&response->response.buffer);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include "rc_api_user.h"
|
||||
#include "rc_api_common.h"
|
||||
#include "rc_consoles.h"
|
||||
|
||||
#include "../rc_version.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* --- Login --- */
|
||||
|
@ -252,3 +254,101 @@ int rc_api_process_fetch_user_unlocks_server_response(rc_api_fetch_user_unlocks_
|
|||
void rc_api_destroy_fetch_user_unlocks_response(rc_api_fetch_user_unlocks_response_t* response) {
|
||||
rc_buffer_destroy(&response->response.buffer);
|
||||
}
|
||||
|
||||
/* --- Fetch All Progress --- */
|
||||
|
||||
int rc_api_init_fetch_all_progress_request(rc_api_request_t* request,
|
||||
const rc_api_fetch_all_progress_request_t* api_params)
|
||||
{
|
||||
rc_api_url_builder_t builder;
|
||||
|
||||
rc_api_url_build_dorequest_url(request);
|
||||
|
||||
if (api_params->console_id == RC_CONSOLE_UNKNOWN)
|
||||
return RC_INVALID_STATE;
|
||||
|
||||
rc_url_builder_init(&builder, &request->buffer, 48);
|
||||
if (rc_api_url_build_dorequest(&builder, "allprogress", api_params->username, api_params->api_token))
|
||||
{
|
||||
rc_url_builder_append_unum_param(&builder, "c", api_params->console_id);
|
||||
request->post_data = rc_url_builder_finalize(&builder);
|
||||
request->content_type = RC_CONTENT_TYPE_URLENCODED;
|
||||
}
|
||||
|
||||
return builder.result;
|
||||
}
|
||||
|
||||
int rc_api_process_fetch_all_progress_server_response(rc_api_fetch_all_progress_response_t* response,
|
||||
const rc_api_server_response_t* server_response)
|
||||
{
|
||||
rc_api_all_progress_entry_t* entry;
|
||||
rc_json_iterator_t iterator;
|
||||
rc_json_field_t field;
|
||||
int result;
|
||||
char* end;
|
||||
|
||||
rc_json_field_t fields[] = {
|
||||
RC_JSON_NEW_FIELD("Success"),
|
||||
RC_JSON_NEW_FIELD("Error"),
|
||||
RC_JSON_NEW_FIELD("Response"),
|
||||
};
|
||||
|
||||
rc_json_field_t entry_fields[] = {
|
||||
RC_JSON_NEW_FIELD("Achievements"),
|
||||
RC_JSON_NEW_FIELD("Unlocked"),
|
||||
RC_JSON_NEW_FIELD("UnlockedHardcore"),
|
||||
};
|
||||
|
||||
memset(response, 0, sizeof(*response));
|
||||
rc_buffer_init(&response->response.buffer);
|
||||
|
||||
result =
|
||||
rc_json_parse_server_response(&response->response, server_response, fields, sizeof(fields) / sizeof(fields[0]));
|
||||
if (result != RC_OK)
|
||||
return result;
|
||||
|
||||
if (!fields[2].value_start)
|
||||
{
|
||||
/* call rc_json_get_required_object to generate the error message */
|
||||
rc_json_get_required_object(NULL, 0, &response->response, &fields[2], "Response");
|
||||
return RC_MISSING_VALUE;
|
||||
}
|
||||
|
||||
response->num_entries = fields[2].array_size;
|
||||
rc_buffer_reserve(&response->response.buffer, response->num_entries * sizeof(rc_api_all_progress_entry_t));
|
||||
|
||||
response->entries = (rc_api_all_progress_entry_t*)rc_buffer_alloc(
|
||||
&response->response.buffer, response->num_entries * sizeof(rc_api_all_progress_entry_t));
|
||||
if (!response->entries)
|
||||
return RC_OUT_OF_MEMORY;
|
||||
|
||||
memset(&iterator, 0, sizeof(iterator));
|
||||
iterator.json = fields[2].value_start;
|
||||
iterator.end = fields[2].value_end;
|
||||
|
||||
entry = response->entries;
|
||||
while (rc_json_get_next_object_field(&iterator, &field))
|
||||
{
|
||||
entry->game_id = strtol(field.name, &end, 10);
|
||||
|
||||
field.name = "";
|
||||
if (!rc_json_get_required_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]), response, &field,
|
||||
""))
|
||||
{
|
||||
return RC_MISSING_VALUE;
|
||||
}
|
||||
|
||||
rc_json_get_optional_unum(&entry->num_achievements, &entry_fields[0], "Achievements", 0);
|
||||
rc_json_get_optional_unum(&entry->num_unlocked_achievements, &entry_fields[1], "Unlocked", 0);
|
||||
rc_json_get_optional_unum(&entry->num_unlocked_achievements_hardcore, &entry_fields[2], "UnlockedHardcore", 0);
|
||||
|
||||
++entry;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
void rc_api_destroy_fetch_all_progress_response(rc_api_fetch_all_progress_response_t* response)
|
||||
{
|
||||
rc_buffer_destroy(&response->response.buffer);
|
||||
}
|
||||
|
|
|
@ -3209,6 +3209,272 @@ const rc_client_subset_t* rc_client_get_subset_info(rc_client_t* client, uint32_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* ===== Game Info ===== */
|
||||
|
||||
typedef struct rc_client_fetch_hash_library_callback_data_t
|
||||
{
|
||||
rc_client_t* client;
|
||||
rc_client_fetch_hash_library_callback_t callback;
|
||||
void* callback_userdata;
|
||||
uint32_t console_id;
|
||||
rc_client_async_handle_t async_handle;
|
||||
} rc_client_fetch_hash_library_callback_data_t;
|
||||
|
||||
static void rc_client_fetch_hash_library_callback(const rc_api_server_response_t* server_response, void* callback_data)
|
||||
{
|
||||
rc_client_fetch_hash_library_callback_data_t* hashlib_callback_data =
|
||||
(rc_client_fetch_hash_library_callback_data_t*)callback_data;
|
||||
rc_client_t* client = hashlib_callback_data->client;
|
||||
rc_api_fetch_hash_library_response_t hashlib_response;
|
||||
const char* error_message;
|
||||
int result;
|
||||
|
||||
result = rc_client_end_async(client, &hashlib_callback_data->async_handle);
|
||||
if (result)
|
||||
{
|
||||
if (result != RC_CLIENT_ASYNC_DESTROYED)
|
||||
RC_CLIENT_LOG_VERBOSE(client, "Fetch hash library aborted");
|
||||
|
||||
free(hashlib_callback_data);
|
||||
return;
|
||||
}
|
||||
|
||||
result = rc_api_process_fetch_hash_library_server_response(&hashlib_response, server_response);
|
||||
error_message =
|
||||
rc_client_server_error_message(&result, server_response->http_status_code, &hashlib_response.response);
|
||||
if (error_message)
|
||||
{
|
||||
RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch hash library for console %u failed: %s",
|
||||
hashlib_callback_data->console_id, error_message);
|
||||
hashlib_callback_data->callback(result, error_message, NULL, client, hashlib_callback_data->callback_userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc_client_hash_library_t* list;
|
||||
const size_t list_size = sizeof(*list) + sizeof(rc_client_leaderboard_entry_t) * hashlib_response.num_entries;
|
||||
size_t needed_size = list_size;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < hashlib_response.num_entries; i++)
|
||||
needed_size += strlen(hashlib_response.entries[i].hash) + 1;
|
||||
|
||||
list = (rc_client_hash_library_t*)malloc(needed_size);
|
||||
if (!list)
|
||||
{
|
||||
hashlib_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client,
|
||||
hashlib_callback_data->callback_userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc_client_hash_library_entry_t* entry = list->entries =
|
||||
(rc_client_hash_library_entry_t*)((uint8_t*)list + sizeof(*list));
|
||||
char* hash = (char*)((uint8_t*)list + list_size);
|
||||
const rc_api_hash_library_entry_t* hlentry = hashlib_response.entries;
|
||||
const rc_api_hash_library_entry_t* stop = hlentry + hashlib_response.num_entries;
|
||||
|
||||
for (; hlentry < stop; ++hlentry, ++entry)
|
||||
{
|
||||
const size_t len = strlen(hlentry->hash) + 1;
|
||||
entry->hash = hash;
|
||||
entry->game_id = hlentry->game_id;
|
||||
memcpy(hash, hlentry->hash, len);
|
||||
hash += len;
|
||||
}
|
||||
|
||||
list->num_entries = hashlib_response.num_entries;
|
||||
|
||||
hashlib_callback_data->callback(RC_OK, NULL, list, client, hashlib_callback_data->callback_userdata);
|
||||
}
|
||||
}
|
||||
|
||||
rc_api_destroy_fetch_hash_library_response(&hashlib_response);
|
||||
free(hashlib_callback_data);
|
||||
}
|
||||
|
||||
rc_client_async_handle_t* rc_client_begin_fetch_hash_library(rc_client_t* client, uint32_t console_id,
|
||||
rc_client_fetch_hash_library_callback_t callback,
|
||||
void* callback_userdata)
|
||||
{
|
||||
rc_api_fetch_hash_library_request_t api_params;
|
||||
rc_client_fetch_hash_library_callback_data_t* callback_data;
|
||||
rc_client_async_handle_t* async_handle;
|
||||
rc_api_request_t request;
|
||||
int result;
|
||||
const char* error_message;
|
||||
|
||||
if (!client)
|
||||
{
|
||||
callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
api_params.console_id = console_id;
|
||||
result = rc_api_init_fetch_hash_library_request(&request, &api_params);
|
||||
|
||||
if (result != RC_OK)
|
||||
{
|
||||
error_message = rc_error_str(result);
|
||||
callback(result, error_message, NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
callback_data = (rc_client_fetch_hash_library_callback_data_t*)calloc(1, sizeof(*callback_data));
|
||||
if (!callback_data)
|
||||
{
|
||||
callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
callback_data->client = client;
|
||||
callback_data->callback = callback;
|
||||
callback_data->callback_userdata = callback_userdata;
|
||||
callback_data->console_id = console_id;
|
||||
|
||||
async_handle = &callback_data->async_handle;
|
||||
rc_client_begin_async(client, async_handle);
|
||||
client->callbacks.server_call(&request, rc_client_fetch_hash_library_callback, callback_data, client);
|
||||
rc_api_destroy_request(&request);
|
||||
|
||||
return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL;
|
||||
}
|
||||
|
||||
void rc_client_destroy_hash_library(rc_client_hash_library_t* list)
|
||||
{
|
||||
free(list);
|
||||
}
|
||||
|
||||
typedef struct rc_client_fetch_all_progress_callback_data_t
|
||||
{
|
||||
rc_client_t* client;
|
||||
rc_client_fetch_all_progress_list_callback_t callback;
|
||||
void* callback_userdata;
|
||||
uint32_t console_id;
|
||||
rc_client_async_handle_t async_handle;
|
||||
} rc_client_fetch_all_progress_callback_data_t;
|
||||
|
||||
static void rc_client_fetch_all_progress_callback(const rc_api_server_response_t* server_response, void* callback_data)
|
||||
{
|
||||
rc_client_fetch_all_progress_callback_data_t* ap_callback_data =
|
||||
(rc_client_fetch_all_progress_callback_data_t*)callback_data;
|
||||
rc_client_t* client = ap_callback_data->client;
|
||||
rc_api_fetch_all_progress_response_t ap_response;
|
||||
const char* error_message;
|
||||
int result;
|
||||
|
||||
result = rc_client_end_async(client, &ap_callback_data->async_handle);
|
||||
if (result)
|
||||
{
|
||||
if (result != RC_CLIENT_ASYNC_DESTROYED)
|
||||
RC_CLIENT_LOG_VERBOSE(client, "Fetch all progress aborted");
|
||||
|
||||
free(ap_callback_data);
|
||||
return;
|
||||
}
|
||||
|
||||
result = rc_api_process_fetch_all_progress_server_response(&ap_response, server_response);
|
||||
error_message = rc_client_server_error_message(&result, server_response->http_status_code, &ap_response.response);
|
||||
if (error_message)
|
||||
{
|
||||
RC_CLIENT_LOG_ERR_FORMATTED(client, "Fetch all progress for console %u failed: %s", ap_callback_data->console_id,
|
||||
error_message);
|
||||
ap_callback_data->callback(result, error_message, NULL, client, ap_callback_data->callback_userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc_client_all_progress_list_t* list;
|
||||
const size_t list_size = sizeof(*list) + sizeof(rc_client_all_progress_list_entry_t) * ap_response.num_entries;
|
||||
|
||||
list = (rc_client_all_progress_list_t*)malloc(list_size);
|
||||
if (!list)
|
||||
{
|
||||
ap_callback_data->callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client,
|
||||
ap_callback_data->callback_userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc_client_all_progress_list_entry_t* entry = list->entries =
|
||||
(rc_client_all_progress_list_entry_t*)((uint8_t*)list + sizeof(*list));
|
||||
const rc_api_all_progress_entry_t* hlentry = ap_response.entries;
|
||||
const rc_api_all_progress_entry_t* stop = hlentry + ap_response.num_entries;
|
||||
|
||||
for (; hlentry < stop; ++hlentry, ++entry)
|
||||
{
|
||||
entry->game_id = hlentry->game_id;
|
||||
entry->num_achievements = hlentry->num_achievements;
|
||||
entry->num_unlocked_achievements = hlentry->num_unlocked_achievements;
|
||||
entry->num_unlocked_achievements_hardcore = hlentry->num_unlocked_achievements_hardcore;
|
||||
}
|
||||
|
||||
list->num_entries = ap_response.num_entries;
|
||||
|
||||
ap_callback_data->callback(RC_OK, NULL, list, client, ap_callback_data->callback_userdata);
|
||||
}
|
||||
}
|
||||
|
||||
rc_api_destroy_fetch_all_progress_response(&ap_response);
|
||||
free(ap_callback_data);
|
||||
}
|
||||
|
||||
rc_client_async_handle_t* rc_client_begin_fetch_all_progress_list(rc_client_t* client, uint32_t console_id,
|
||||
rc_client_fetch_all_progress_list_callback_t callback,
|
||||
void* callback_userdata)
|
||||
{
|
||||
rc_api_fetch_all_progress_request_t api_params;
|
||||
rc_client_fetch_all_progress_callback_data_t* callback_data;
|
||||
rc_client_async_handle_t* async_handle;
|
||||
rc_api_request_t request;
|
||||
int result;
|
||||
const char* error_message;
|
||||
|
||||
if (!client)
|
||||
{
|
||||
callback(RC_INVALID_STATE, "client is required", NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
else if (client->state.user != RC_CLIENT_USER_STATE_LOGGED_IN)
|
||||
{
|
||||
callback(RC_INVALID_STATE, "client must be logged in", NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
api_params.username = client->user.username;
|
||||
api_params.api_token = client->user.token;
|
||||
api_params.console_id = console_id;
|
||||
|
||||
result = rc_api_init_fetch_all_progress_request(&request, &api_params);
|
||||
|
||||
if (result != RC_OK)
|
||||
{
|
||||
error_message = rc_error_str(result);
|
||||
callback(result, error_message, NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
callback_data = (rc_client_fetch_all_progress_callback_data_t*)calloc(1, sizeof(*callback_data));
|
||||
if (!callback_data)
|
||||
{
|
||||
callback(RC_OUT_OF_MEMORY, rc_error_str(RC_OUT_OF_MEMORY), NULL, client, callback_userdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
callback_data->client = client;
|
||||
callback_data->callback = callback;
|
||||
callback_data->callback_userdata = callback_userdata;
|
||||
callback_data->console_id = console_id;
|
||||
|
||||
async_handle = &callback_data->async_handle;
|
||||
rc_client_begin_async(client, async_handle);
|
||||
client->callbacks.server_call(&request, rc_client_fetch_all_progress_callback, callback_data, client);
|
||||
rc_api_destroy_request(&request);
|
||||
|
||||
return rc_client_async_handle_valid(client, async_handle) ? async_handle : NULL;
|
||||
}
|
||||
|
||||
void rc_client_destroy_all_progress_list(rc_client_all_progress_list_t* list)
|
||||
{
|
||||
free(list);
|
||||
}
|
||||
|
||||
/* ===== Achievements ===== */
|
||||
|
||||
static void rc_client_update_achievement_display_information(rc_client_t* client, rc_client_achievement_info_t* achievement, time_t recent_unlock_time)
|
||||
|
@ -3675,6 +3941,20 @@ static int rc_client_is_award_achievement_pending(const rc_client_t* client, uin
|
|||
return 0;
|
||||
}
|
||||
|
||||
int rc_client_get_award_achievement_pending_count(rc_client_t* client)
|
||||
{
|
||||
/* assume lock already held */
|
||||
int count = 0;
|
||||
rc_client_scheduled_callback_data_t* scheduled_callback = client->state.scheduled_callbacks;
|
||||
for (; scheduled_callback; scheduled_callback = scheduled_callback->next)
|
||||
{
|
||||
if (scheduled_callback->callback == rc_client_award_achievement_retry)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void rc_client_award_achievement_server_call(rc_client_award_achievement_callback_data_t* ach_data);
|
||||
|
||||
static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now)
|
||||
|
@ -4185,10 +4465,10 @@ void rc_client_destroy_leaderboard_list(rc_client_leaderboard_list_t* list)
|
|||
free(list);
|
||||
}
|
||||
|
||||
int rc_client_has_leaderboards(rc_client_t* client)
|
||||
int rc_client_has_leaderboards(rc_client_t* client, int include_hidden)
|
||||
{
|
||||
rc_client_subset_info_t* subset;
|
||||
int result;
|
||||
int i, result;
|
||||
|
||||
if (!client)
|
||||
return 0;
|
||||
|
@ -4211,8 +4491,20 @@ int rc_client_has_leaderboards(rc_client_t* client)
|
|||
continue;
|
||||
|
||||
if (subset->public_.num_leaderboards > 0) {
|
||||
result = 1;
|
||||
break;
|
||||
if (!include_hidden) {
|
||||
for (i = 0; i < subset->public_.num_leaderboards; i++) {
|
||||
if (subset->leaderboards[i].hidden)
|
||||
continue;
|
||||
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
if (result)
|
||||
break;
|
||||
} else {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6145,3 +6437,8 @@ size_t rc_client_get_user_agent_clause(rc_client_t* client, char buffer[], size_
|
|||
buffer[buffer_size - 1] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
int rc_client_is_disconnected(rc_client_t* client)
|
||||
{
|
||||
return (client && (client->state.disconnect & (RC_CLIENT_DISCONNECT_VISIBLE | RC_CLIENT_DISCONNECT_SHOW_PENDING) != 0));
|
||||
}
|
||||
|
|
|
@ -465,6 +465,17 @@ int rc_operand_type_is_memref(uint8_t type) {
|
|||
}
|
||||
}
|
||||
|
||||
int rc_operand_type_is_transform(uint8_t type) {
|
||||
switch (type) {
|
||||
case RC_OPERAND_BCD:
|
||||
case RC_OPERAND_INVERTED:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rc_operand_is_memref(const rc_operand_t* self) {
|
||||
return rc_operand_type_is_memref(self->type);
|
||||
}
|
||||
|
@ -603,9 +614,15 @@ void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t n
|
|||
|
||||
self->value.memref = (rc_memref_t*)modified_memref;
|
||||
|
||||
/* if adding a constant, change the type to be address (current value) */
|
||||
if (!rc_operand_is_memref(self))
|
||||
if (!rc_operand_is_memref(self)) {
|
||||
/* if adding a constant, change the type to be address (current value) */
|
||||
self->type = self->memref_access_type = RC_OPERAND_ADDRESS;
|
||||
}
|
||||
else if (rc_operand_type_is_transform(self->type)) {
|
||||
/* transform is applied in the modified_memref. change the type to be
|
||||
* address (current value) to avoid applying the transform again */
|
||||
self->type = self->memref_access_type = RC_OPERAND_ADDRESS;
|
||||
}
|
||||
|
||||
/* result of an AddSource operation is always a 32-bit integer (even if parent or modifier is a float) */
|
||||
self->size = RC_MEMSIZE_32_BITS;
|
||||
|
|
|
@ -352,6 +352,7 @@ int rc_operand_is_float_memref(const rc_operand_t* self);
|
|||
int rc_operand_is_float(const rc_operand_t* self);
|
||||
int rc_operand_is_recall(const rc_operand_t* self);
|
||||
int rc_operand_type_is_memref(uint8_t type);
|
||||
int rc_operand_type_is_transform(uint8_t type);
|
||||
int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right);
|
||||
void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t new_size);
|
||||
void rc_operand_set_const(rc_operand_t* self, uint32_t value);
|
||||
|
|
|
@ -55,6 +55,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reshadefx", "dep\reshadefx\
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rapidyaml", "dep\rapidyaml\rapidyaml.vcxproj", "{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "duckstation-mini", "src\duckstation-mini\duckstation-mini.vcxproj", "{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
|
@ -967,6 +969,28 @@ Global
|
|||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Debug-Clang|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Debug-Clang|x64.ActiveCfg = Debug-Clang|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Debug-Clang-SSE2|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Debug-Clang-SSE2|x64.ActiveCfg = Debug-Clang-SSE2|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.DebugFast|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Release|x64.ActiveCfg = Release|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.Release-Clang|x64.ActiveCfg = Release-Clang|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.ReleaseLTCG-Clang|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{FA259BC0-1007-4FD9-8A47-87CC0ECB8445}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -336,7 +336,8 @@ def check_regression_test(baselinedir, testdir, name):
|
|||
|
||||
def check_regression_tests(baselinedir, testdir):
|
||||
gamedirs = glob.glob(baselinedir + "/*", recursive=False)
|
||||
|
||||
gamedirs.sort(key=lambda x: os.path.basename(x))
|
||||
|
||||
success = 0
|
||||
failure = 0
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 4 ]; then
|
||||
echo "Syntax: $0 [-system-freetype] [-system-harfbuzz] [-system-libjpeg] [-system-libpng] [-system-libwebp] [-system-libzip] [-system-zstd] [-system-qt] [-skip-download] [-skip-cleanup] [-only-download] <host directory> <cross architecture> <cross chroot> <output directory>"
|
||||
echo "Syntax: $0 [-system-freetype] [-system-harfbuzz] [-system-libjpeg] [-system-libpng] [-system-libwebp] [-system-libzip] [-system-zlib] [-system-zstd] [-system-qt] [-skip-download] [-skip-cleanup] [-only-download] <host directory> <cross architecture> <cross chroot> <output directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -35,6 +35,10 @@ for arg in "$@"; do
|
|||
echo "Skipping building libzip."
|
||||
SKIP_LIBZIP=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-zlib" ]; then
|
||||
echo "Skipping building zlib-ng."
|
||||
SKIP_ZLIBNG=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-zstd" ]; then
|
||||
echo "Skipping building zstd."
|
||||
SKIP_ZSTD=true
|
||||
|
@ -81,34 +85,49 @@ CMAKE_COMMON=(
|
|||
-DCMAKE_INSTALL_PREFIX="$INSTALLDIR"
|
||||
)
|
||||
|
||||
# Determine architecture.
|
||||
if [ "$CROSSARCH" == "arm64" ]; then
|
||||
CROSSSYSARCH="aarch64"
|
||||
CROSSTRIPLET="aarch64-linux-gnu"
|
||||
CMAKEPROCESSOR="aarch64"
|
||||
elif [ "$CROSSARCH" == "armhf" ]; then
|
||||
CROSSSYSARCH="armhf"
|
||||
CROSSTRIPLET="arm-linux-gnueabihf"
|
||||
CMAKEPROCESSOR="armv7-a"
|
||||
else
|
||||
echo "Unknown cross arch $CROSSARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# TODO: Pull all of this from the main file.
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.1.0
|
||||
HARFBUZZ=10.2.0
|
||||
LIBBACKTRACE=86885d14049fab06ef8a33aac51664230ca09200
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBPNG=1.6.44
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.2
|
||||
SDL2=2.30.11
|
||||
QT=6.8.1
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.45
|
||||
LIBWEBP=1.5.0
|
||||
LIBZIP=1.11.3
|
||||
SDL3=3.2.8
|
||||
QT=6.8.2
|
||||
ZLIBNG=2.2.4
|
||||
ZSTD=1.5.6
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
LUNASVG=9af1ac7b90658a279b372add52d6f77a4ebb482c
|
||||
SHADERC=1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6
|
||||
CPUINFO=3ebbfd45645650c4940bf0f3b4d25ab913466bb0
|
||||
DISCORD_RPC=cc59d26d1d628fbd6527aac0ac1d6301f4978b92
|
||||
LUNASVG=4a1c98ccb1da8a5a92ddc4f97339869b1ae556f4
|
||||
SHADERC=fc65b19d2098cf81e55b4edc10adad2ad8268361
|
||||
SOUNDTOUCH=463ade388f3a51da078dc9ed062bf28e4ba29da7
|
||||
SPIRV_CROSS=vulkan-sdk-1.3.290.0
|
||||
SPIRV_CROSS=vulkan-sdk-1.4.304.0
|
||||
|
||||
mkdir -p "${INSTALLDIR}"
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libbacktrace-$LIBBACKTRACE.tar.gz" ]]; then
|
||||
curl -C - -L \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.tar.gz" \
|
||||
-O "https://github.com/libsdl-org/SDL/releases/download/release-$SDL2/SDL2-$SDL2.tar.gz" \
|
||||
-o "libbacktrace-$LIBBACKTRACE.tar.gz" "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.tar.gz" \
|
||||
-O "https://github.com/libsdl-org/SDL/releases/download/release-$SDL3/SDL3-$SDL3.tar.gz" \
|
||||
-o "cpuinfo-$CPUINFO.tar.gz" "https://github.com/stenzek/cpuinfo/archive/$CPUINFO.tar.gz" \
|
||||
-o "discord-rpc-$DISCORD_RPC.tar.gz" "https://github.com/stenzek/discord-rpc/archive/$DISCORD_RPC.tar.gz" \
|
||||
-o "lunasvg-$LUNASVG.tar.gz" "https://github.com/stenzek/lunasvg/archive/$LUNASVG.tar.gz" \
|
||||
|
@ -117,17 +136,17 @@ if [ "$SKIP_DOWNLOAD" != true ]; then
|
|||
fi
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
baf8aebd22002b762d803ba0e1e389b6b4415159334e9d34bba1a938f6de8ce6 $LIBBACKTRACE.tar.gz
|
||||
8b8d4aef2038533da814965220f88f77d60dfa0f32685f80ead65e501337da7f SDL2-$SDL2.tar.gz
|
||||
e1351218d270db49c3dddcba04fb2153b09731ea3fa6830e423f5952f44585be cpuinfo-$CPUINFO.tar.gz
|
||||
3eea5ccce6670c126282f1ba4d32c19d486db49a1a5cbfb8d6f48774784d310c discord-rpc-$DISCORD_RPC.tar.gz
|
||||
3998b024b0d442614a9ee270e76e018bb37a17b8c6941212171731123cbbcac7 lunasvg-$LUNASVG.tar.gz
|
||||
3826d86f8a13564be1c047ac105041a3c5d0dc0bf826fe47cc582fe17a2ce7b1 shaderc-$SHADERC.tar.gz
|
||||
baf8aebd22002b762d803ba0e1e389b6b4415159334e9d34bba1a938f6de8ce6 libbacktrace-$LIBBACKTRACE.tar.gz
|
||||
13388fabb361de768ecdf2b65e52bb27d1054cae6ccb6942ba926e378e00db03 SDL3-$SDL3.tar.gz
|
||||
b60832071919220d2fe692151fb420fa9ea489aa4c7a2eb0e01c830cbe469858 cpuinfo-$CPUINFO.tar.gz
|
||||
297cd48a287a9113eec44902574084c6ab3b6a8b28d02606765a7fded431d7d8 discord-rpc-$DISCORD_RPC.tar.gz
|
||||
5fe7abc6c4601f21fa56ffbf12507e80684942c3134b7888701ede836e6287e2 lunasvg-$LUNASVG.tar.gz
|
||||
d1ef912c27e06307f2b2a5b6386070d0b8fae2bb5851f50841df7b73dcf5abdf shaderc-$SHADERC.tar.gz
|
||||
fe45c2af99f6102d2704277d392c1c83b55180a70bfd17fb888cc84a54b70573 soundtouch-$SOUNDTOUCH.tar.gz
|
||||
EOF
|
||||
|
||||
if [ "$SKIP_FREETYPE" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "freetype-$FREETYPE.tar.xz" ]]; then
|
||||
curl -C - -L -o "freetype-$FREETYPE.tar.xz" "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz/download"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
|
@ -135,47 +154,55 @@ if [ "$SKIP_FREETYPE" != true ]; then
|
|||
EOF
|
||||
fi
|
||||
if [ "$SKIP_HARFBUZZ" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "harfbuzz-$HARFBUZZ.tar.gz" ]]; then
|
||||
curl -C - -L -o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
11749926914fd488e08e744538f19329332487a6243eec39ef3c63efa154a578 harfbuzz-$HARFBUZZ.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBJPEG" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libjpeg-turbo-$LIBJPEGTURBO.tar.gz" ]]; then
|
||||
curl -C - -L -O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBPNG" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libpng-$LIBPNG.tar.xz" ]]; then
|
||||
curl -C - -L -O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
60c4da1d5b7f0aa8d158da48e8f8afa9773c1c8baa5d21974df61f1886b8ce8e libpng-$LIBPNG.tar.xz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBWEBP" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libwebp-$LIBWEBP.tar.gz" ]]; then
|
||||
curl -C - -L -O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBZIP" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libzip-$LIBZIP.tar.xz" ]]; then
|
||||
curl -C - -L -O "https://github.com/nih-at/libzip/releases/download/v$LIBZIP/libzip-$LIBZIP.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
9509d878ba788271c8b5abca9cfde1720f075335686237b7e9a9e7210fe67c1b libzip-$LIBZIP.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZLIBNG" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "zlib-ng-$ZLIBNG.tar.gz" ]]; then
|
||||
curl -C - -L -o "zlib-ng-$ZLIBNG.tar.gz" "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/$ZLIBNG.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
a73343c3093e5cdc50d9377997c3815b878fd110bf6511c2c7759f2afb90f5a3 zlib-ng-$ZLIBNG.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZSTD" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "zstd-$ZSTD.tar.gz" ]]; then
|
||||
curl -C - -L -O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
|
@ -183,7 +210,7 @@ if [ "$SKIP_ZSTD" != true ]; then
|
|||
EOF
|
||||
fi
|
||||
if [ "$SKIP_QT" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "qtbase-everywhere-src-$QT.tar.xz" ]]; then
|
||||
curl -C - -L \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
|
@ -193,22 +220,20 @@ if [ "$SKIP_QT" != true ]; then
|
|||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtwayland-everywhere-src-$QT.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
40b14562ef3bd779bc0e0418ea2ae08fa28235f8ea6e8c0cb3bce1d6ad58dcaf qtbase-everywhere-src-$QT.tar.xz
|
||||
138cc2909aa98f5ff7283e36eb3936eb5e625d3ca3b4febae2ca21d8903dd237 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
3d0de73596e36b2daa7c48d77c4426bb091752856912fba720215f756c560dd0 qtsvg-everywhere-src-$QT.tar.xz
|
||||
9d43d409be08b8681a0155a9c65114b69c9a3fc11aef6487bb7fdc5b283c432d qttools-everywhere-src-$QT.tar.xz
|
||||
635a6093e99152243b807de51077485ceadd4786d4acb135b9340b2303035a4a qttranslations-everywhere-src-$QT.tar.xz
|
||||
2226fbde4e2ddd12f8bf4b239c8f38fd706a54e789e63467dfddc77129eca203 qtwayland-everywhere-src-$QT.tar.xz
|
||||
012043ce6d411e6e8a91fdc4e05e6bedcfa10fcb1347d3c33908f7fdd10dfe05 qtbase-everywhere-src-$QT.tar.xz
|
||||
d2a1bbb84707b8a0aec29227b170be00f04383fbf2361943596d09e7e443c8e1 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
aa2579f21ca66d19cbcf31d87e9067e07932635d36869c8239d4decd0a9dc1fa qtsvg-everywhere-src-$QT.tar.xz
|
||||
326381b7d43f07913612f291abc298ae79bd95382e2233abce982cff2b53d2c0 qttools-everywhere-src-$QT.tar.xz
|
||||
d2106e8a580bfd77702c4c1840299288d344902b0e2c758ca813ea04c6d6a3d1 qttranslations-everywhere-src-$QT.tar.xz
|
||||
5e46157908295f2bf924462d8c0855b0508ba338ced9e810891fefa295dc9647 qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
fi
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
# Have to clone with git, because it does version detection.
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [ ! -d "SPIRV-Cross" ]; then
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Cross/ -b $SPIRV_CROSS --depth 1
|
||||
fi
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -d "SPIRV-Cross" ]]; then
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Cross/ -b $SPIRV_CROSS --depth 1
|
||||
fi
|
||||
|
||||
# Only downloading sources?
|
||||
|
@ -217,24 +242,24 @@ if [ "$ONLY_DOWNLOAD" == true ]; then
|
|||
fi
|
||||
|
||||
# Stop pkg-config picking up host files.
|
||||
export PKG_CONFIG_PATH=${SYSROOTDIR}/usr/lib/${CROSSARCH}-linux-gnu/pkgconfig:${SYSROOTDIR}/usr/lib/pkgconfig:${SYSROOTDIR}/usr/share/pkgconfig
|
||||
export PKG_CONFIG_PATH=${SYSROOTDIR}/usr/lib/${CROSSTRIPLET}/pkgconfig:${SYSROOTDIR}/usr/lib/pkgconfig:${SYSROOTDIR}/usr/share/pkgconfig
|
||||
export PKG_CONFIG_SYSROOT_DIR=${SYSROOTDIR}
|
||||
|
||||
# Generate cmake toolchain file.
|
||||
cat > "$TOOLCHAINFILE" << EOF
|
||||
set(CMAKE_CROSSCOMPILING TRUE)
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CROSSARCH})
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKEPROCESSOR})
|
||||
|
||||
set(CMAKE_C_COMPILER "/usr/bin/${CROSSARCH}-linux-gnu-gcc")
|
||||
set(CMAKE_C_COMPILER_TARGET "${CROSSARCH}-linux-gnu")
|
||||
set(CMAKE_C_COMPILER_AR "/usr/bin/${CROSSARCH}-linux-gnu-ar")
|
||||
set(CMAKE_C_COMPILER_RANLIB "/usr/bin/${CROSSARCH}-linux-gnu-ranlib")
|
||||
set(CMAKE_C_COMPILER "/usr/bin/${CROSSTRIPLET}-gcc")
|
||||
set(CMAKE_C_COMPILER_TARGET "${CROSSTRIPLET}")
|
||||
set(CMAKE_C_COMPILER_AR "/usr/bin/${CROSSTRIPLET}-ar")
|
||||
set(CMAKE_C_COMPILER_RANLIB "/usr/bin/${CROSSTRIPLET}-ranlib")
|
||||
|
||||
set(CMAKE_CXX_COMPILER "/usr/bin/${CROSSARCH}-linux-gnu-g++")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "${CROSSARCH}-linux-gnu")
|
||||
set(CMAKE_CXX_COMPILER_AR "/usr/bin/${CROSSARCH}-linux-gnu-ar")
|
||||
set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/${CROSSARCH}-linux-gnu-ranlib")
|
||||
set(CMAKE_CXX_COMPILER "/usr/bin/${CROSSTRIPLET}-g++")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "${CROSSTRIPLET}")
|
||||
set(CMAKE_CXX_COMPILER_AR "/usr/bin/${CROSSTRIPLET}-ar")
|
||||
set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/${CROSSTRIPLET}-ranlib")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH "${INSTALLDIR};${SYSROOTDIR}")
|
||||
set(CMAKE_SYSROOT "${SYSROOTDIR}")
|
||||
|
@ -248,12 +273,25 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
EOF
|
||||
|
||||
# Build zlib first because of the things that depend on it.
|
||||
# Disabled because it currently causes crashes on armhf.
|
||||
#if [ "$SKIP_ZLIBNG" != true ]; then
|
||||
# echo "Building zlib-ng..."
|
||||
# rm -fr "zlib-ng-$ZLIBNG"
|
||||
# tar xf "zlib-ng-$ZLIBNG.tar.gz"
|
||||
# cd "zlib-ng-$ZLIBNG"
|
||||
# cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DZLIB_COMPAT=ON -DZLIBNG_ENABLE_TESTS=OFF -DZLIB_ENABLE_TESTS=OFF -DWITH_GTEST=OFF -B build -G Ninja
|
||||
# cmake --build build --parallel
|
||||
# ninja -C build install
|
||||
# cd ..
|
||||
#fi
|
||||
|
||||
# NOTE: Must be a shared library because otherwise aarch64 libgcc symbols are missing when building with clang.
|
||||
echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
tar xf "$LIBBACKTRACE.tar.gz"
|
||||
tar xf "libbacktrace-$LIBBACKTRACE.tar.gz"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$INSTALLDIR" --build=x86_64-linux-gnu --host="${CROSSARCH}-linux-gnu" --with-pic --enable-shared --disable-static
|
||||
./configure --prefix="$INSTALLDIR" --build=x86_64-linux-gnu --host="${CROSSTRIPLET}" --with-pic --enable-shared --disable-static
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
|
@ -349,13 +387,11 @@ if [ "$SKIP_FREETYPE" != true ]; then
|
|||
cd ..
|
||||
fi
|
||||
|
||||
echo "Building SDL2..."
|
||||
rm -fr "SDL2-$SDL2"
|
||||
tar xf "SDL2-$SDL2.tar.gz"
|
||||
cd "SDL2-$SDL2"
|
||||
# needed because -Isystem with chroot/usr/include breaks
|
||||
patch -p1 < "$SCRIPTDIR/sdl2-disable-isystem.patch"
|
||||
cmake -B build "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja
|
||||
echo "Building SDL..."
|
||||
rm -fr "SDL3-$SDL3"
|
||||
tar xf "SDL3-$SDL3.tar.gz"
|
||||
cd "SDL3-$SDL3"
|
||||
cmake -B build "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Syntax: $0 [-system-freetype] [-system-harfbuzz] [-system-libjpeg] [-system-libpng] [-system-libwebp] [-system-libzip] [-system-zstd] [-system-qt] [-skip-download] [-skip-cleanup] [-only-download] <output directory>"
|
||||
echo "Syntax: $0 [-system-freetype] [-system-harfbuzz] [-system-libjpeg] [-system-libpng] [-system-libwebp] [-system-libzip] [-system-zlib] [-system-zstd] [-system-qt] [-skip-download] [-skip-cleanup] [-only-download] <output directory>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -35,6 +35,10 @@ for arg in "$@"; do
|
|||
echo "Skipping building libzip."
|
||||
SKIP_LIBZIP=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-zlib" ]; then
|
||||
echo "Skipping building zlib-ng."
|
||||
SKIP_ZLIBNG=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-zstd" ]; then
|
||||
echo "Skipping building zstd."
|
||||
SKIP_ZSTD=true
|
||||
|
@ -66,30 +70,31 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
|||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.1.0
|
||||
HARFBUZZ=10.2.0
|
||||
LIBBACKTRACE=86885d14049fab06ef8a33aac51664230ca09200
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBPNG=1.6.44
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.2
|
||||
SDL2=2.30.11
|
||||
QT=6.8.1
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.45
|
||||
LIBWEBP=1.5.0
|
||||
LIBZIP=1.11.3
|
||||
SDL3=3.2.8
|
||||
QT=6.8.2
|
||||
ZLIBNG=2.2.4
|
||||
ZSTD=1.5.6
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
LUNASVG=9af1ac7b90658a279b372add52d6f77a4ebb482c
|
||||
SHADERC=1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6
|
||||
CPUINFO=3ebbfd45645650c4940bf0f3b4d25ab913466bb0
|
||||
DISCORD_RPC=cc59d26d1d628fbd6527aac0ac1d6301f4978b92
|
||||
LUNASVG=4a1c98ccb1da8a5a92ddc4f97339869b1ae556f4
|
||||
SHADERC=fc65b19d2098cf81e55b4edc10adad2ad8268361
|
||||
SOUNDTOUCH=463ade388f3a51da078dc9ed062bf28e4ba29da7
|
||||
SPIRV_CROSS=vulkan-sdk-1.3.290.0
|
||||
SPIRV_CROSS=vulkan-sdk-1.4.304.0
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libbacktrace-$LIBBACKTRACE.tar.gz" ]]; then
|
||||
curl -C - -L \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.tar.gz" \
|
||||
-O "https://github.com/libsdl-org/SDL/releases/download/release-$SDL2/SDL2-$SDL2.tar.gz" \
|
||||
-o "libbacktrace-$LIBBACKTRACE.tar.gz" "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.tar.gz" \
|
||||
-O "https://github.com/libsdl-org/SDL/releases/download/release-$SDL3/SDL3-$SDL3.tar.gz" \
|
||||
-o "cpuinfo-$CPUINFO.tar.gz" "https://github.com/stenzek/cpuinfo/archive/$CPUINFO.tar.gz" \
|
||||
-o "discord-rpc-$DISCORD_RPC.tar.gz" "https://github.com/stenzek/discord-rpc/archive/$DISCORD_RPC.tar.gz" \
|
||||
-o "lunasvg-$LUNASVG.tar.gz" "https://github.com/stenzek/lunasvg/archive/$LUNASVG.tar.gz" \
|
||||
|
@ -98,17 +103,17 @@ if [ "$SKIP_DOWNLOAD" != true ]; then
|
|||
fi
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
baf8aebd22002b762d803ba0e1e389b6b4415159334e9d34bba1a938f6de8ce6 $LIBBACKTRACE.tar.gz
|
||||
8b8d4aef2038533da814965220f88f77d60dfa0f32685f80ead65e501337da7f SDL2-$SDL2.tar.gz
|
||||
e1351218d270db49c3dddcba04fb2153b09731ea3fa6830e423f5952f44585be cpuinfo-$CPUINFO.tar.gz
|
||||
3eea5ccce6670c126282f1ba4d32c19d486db49a1a5cbfb8d6f48774784d310c discord-rpc-$DISCORD_RPC.tar.gz
|
||||
3998b024b0d442614a9ee270e76e018bb37a17b8c6941212171731123cbbcac7 lunasvg-$LUNASVG.tar.gz
|
||||
3826d86f8a13564be1c047ac105041a3c5d0dc0bf826fe47cc582fe17a2ce7b1 shaderc-$SHADERC.tar.gz
|
||||
baf8aebd22002b762d803ba0e1e389b6b4415159334e9d34bba1a938f6de8ce6 libbacktrace-$LIBBACKTRACE.tar.gz
|
||||
13388fabb361de768ecdf2b65e52bb27d1054cae6ccb6942ba926e378e00db03 SDL3-$SDL3.tar.gz
|
||||
b60832071919220d2fe692151fb420fa9ea489aa4c7a2eb0e01c830cbe469858 cpuinfo-$CPUINFO.tar.gz
|
||||
297cd48a287a9113eec44902574084c6ab3b6a8b28d02606765a7fded431d7d8 discord-rpc-$DISCORD_RPC.tar.gz
|
||||
5fe7abc6c4601f21fa56ffbf12507e80684942c3134b7888701ede836e6287e2 lunasvg-$LUNASVG.tar.gz
|
||||
d1ef912c27e06307f2b2a5b6386070d0b8fae2bb5851f50841df7b73dcf5abdf shaderc-$SHADERC.tar.gz
|
||||
fe45c2af99f6102d2704277d392c1c83b55180a70bfd17fb888cc84a54b70573 soundtouch-$SOUNDTOUCH.tar.gz
|
||||
EOF
|
||||
|
||||
if [ "$SKIP_FREETYPE" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "freetype-$FREETYPE.tar.xz" ]]; then
|
||||
curl -C - -L -o "freetype-$FREETYPE.tar.xz" "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz/download"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
|
@ -116,47 +121,55 @@ if [ "$SKIP_FREETYPE" != true ]; then
|
|||
EOF
|
||||
fi
|
||||
if [ "$SKIP_HARFBUZZ" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "harfbuzz-$HARFBUZZ.tar.gz" ]]; then
|
||||
curl -C - -L -o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
11749926914fd488e08e744538f19329332487a6243eec39ef3c63efa154a578 harfbuzz-$HARFBUZZ.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBJPEG" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libjpeg-turbo-$LIBJPEGTURBO.tar.gz" ]]; then
|
||||
curl -C - -L -O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBPNG" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libpng-$LIBPNG.tar.xz" ]]; then
|
||||
curl -C - -L -O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
60c4da1d5b7f0aa8d158da48e8f8afa9773c1c8baa5d21974df61f1886b8ce8e libpng-$LIBPNG.tar.xz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBWEBP" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libwebp-$LIBWEBP.tar.gz" ]]; then
|
||||
curl -C - -L -O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBZIP" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "libzip-$LIBZIP.tar.xz" ]]; then
|
||||
curl -C - -L -O "https://github.com/nih-at/libzip/releases/download/v$LIBZIP/libzip-$LIBZIP.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
9509d878ba788271c8b5abca9cfde1720f075335686237b7e9a9e7210fe67c1b libzip-$LIBZIP.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZLIBNG" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "zlib-ng-$ZLIBNG.tar.gz" ]]; then
|
||||
curl -C - -L -o "zlib-ng-$ZLIBNG.tar.gz" "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/$ZLIBNG.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
a73343c3093e5cdc50d9377997c3815b878fd110bf6511c2c7759f2afb90f5a3 zlib-ng-$ZLIBNG.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZSTD" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "zstd-$ZSTD.tar.gz" ]]; then
|
||||
curl -C - -L -O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
|
@ -164,7 +177,7 @@ if [ "$SKIP_ZSTD" != true ]; then
|
|||
EOF
|
||||
fi
|
||||
if [ "$SKIP_QT" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -f "qtbase-everywhere-src-$QT.tar.xz" ]]; then
|
||||
curl -C - -L \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
|
@ -174,22 +187,20 @@ if [ "$SKIP_QT" != true ]; then
|
|||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtwayland-everywhere-src-$QT.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
40b14562ef3bd779bc0e0418ea2ae08fa28235f8ea6e8c0cb3bce1d6ad58dcaf qtbase-everywhere-src-$QT.tar.xz
|
||||
138cc2909aa98f5ff7283e36eb3936eb5e625d3ca3b4febae2ca21d8903dd237 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
3d0de73596e36b2daa7c48d77c4426bb091752856912fba720215f756c560dd0 qtsvg-everywhere-src-$QT.tar.xz
|
||||
9d43d409be08b8681a0155a9c65114b69c9a3fc11aef6487bb7fdc5b283c432d qttools-everywhere-src-$QT.tar.xz
|
||||
635a6093e99152243b807de51077485ceadd4786d4acb135b9340b2303035a4a qttranslations-everywhere-src-$QT.tar.xz
|
||||
2226fbde4e2ddd12f8bf4b239c8f38fd706a54e789e63467dfddc77129eca203 qtwayland-everywhere-src-$QT.tar.xz
|
||||
012043ce6d411e6e8a91fdc4e05e6bedcfa10fcb1347d3c33908f7fdd10dfe05 qtbase-everywhere-src-$QT.tar.xz
|
||||
d2a1bbb84707b8a0aec29227b170be00f04383fbf2361943596d09e7e443c8e1 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
aa2579f21ca66d19cbcf31d87e9067e07932635d36869c8239d4decd0a9dc1fa qtsvg-everywhere-src-$QT.tar.xz
|
||||
326381b7d43f07913612f291abc298ae79bd95382e2233abce982cff2b53d2c0 qttools-everywhere-src-$QT.tar.xz
|
||||
d2106e8a580bfd77702c4c1840299288d344902b0e2c758ca813ea04c6d6a3d1 qttranslations-everywhere-src-$QT.tar.xz
|
||||
5e46157908295f2bf924462d8c0855b0508ba338ced9e810891fefa295dc9647 qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
fi
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
# Have to clone with git, because it does version detection.
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
if [ ! -d "SPIRV-Cross" ]; then
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Cross/ -b $SPIRV_CROSS --depth 1
|
||||
fi
|
||||
if [[ "$SKIP_DOWNLOAD" != true && ! -d "SPIRV-Cross" ]]; then
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Cross/ -b $SPIRV_CROSS --depth 1
|
||||
fi
|
||||
|
||||
# Only downloading sources?
|
||||
|
@ -197,9 +208,21 @@ if [ "$ONLY_DOWNLOAD" == true ]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
# Build zlib first because of the things that depend on it.
|
||||
if [ "$SKIP_ZLIBNG" != true ]; then
|
||||
echo "Building zlib-ng..."
|
||||
rm -fr "zlib-ng-$ZLIBNG"
|
||||
tar xf "zlib-ng-$ZLIBNG.tar.gz"
|
||||
cd "zlib-ng-$ZLIBNG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DZLIB_COMPAT=ON -DZLIBNG_ENABLE_TESTS=OFF -DZLIB_ENABLE_TESTS=OFF -DWITH_GTEST=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
tar xf "$LIBBACKTRACE.tar.gz"
|
||||
tar xf "libbacktrace-$LIBBACKTRACE.tar.gz"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$INSTALLDIR" --with-pic
|
||||
make
|
||||
|
@ -297,11 +320,11 @@ if [ "$SKIP_FREETYPE" != true ]; then
|
|||
cd ..
|
||||
fi
|
||||
|
||||
echo "Building SDL2..."
|
||||
rm -fr "SDL2-$SDL2"
|
||||
tar xf "SDL2-$SDL2.tar.gz"
|
||||
cd "SDL2-$SDL2"
|
||||
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
|
||||
echo "Building SDL..."
|
||||
rm -fr "SDL3-$SDL3"
|
||||
tar xf "SDL3-$SDL3.tar.gz"
|
||||
cd "SDL3-$SDL3"
|
||||
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 -DSDL_TESTS=OFF -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
|
|
@ -37,23 +37,23 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
|||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.1.0
|
||||
SDL2=2.30.11
|
||||
HARFBUZZ=10.2.0
|
||||
SDL3=3.2.8
|
||||
ZSTD=1.5.6
|
||||
LIBPNG=1.6.44
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.2
|
||||
LIBPNG=1.6.45
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBWEBP=1.5.0
|
||||
LIBZIP=1.11.3
|
||||
FFMPEG=7.1
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.8.1
|
||||
QT=6.8.2
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
CPUINFO=3ebbfd45645650c4940bf0f3b4d25ab913466bb0
|
||||
DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
LUNASVG=9af1ac7b90658a279b372add52d6f77a4ebb482c
|
||||
SHADERC=1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6
|
||||
SHADERC=fc65b19d2098cf81e55b4edc10adad2ad8268361
|
||||
SOUNDTOUCH=463ade388f3a51da078dc9ed062bf28e4ba29da7
|
||||
SPIRV_CROSS=vulkan-sdk-1.3.290.0
|
||||
SPIRV_CROSS=vulkan-sdk-1.4.304.0
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
@ -81,24 +81,24 @@ CMAKE_COMMON_QT=(
|
|||
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
60c4da1d5b7f0aa8d158da48e8f8afa9773c1c8baa5d21974df61f1886b8ce8e libpng-$LIBPNG.tar.xz
|
||||
99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
8b8d4aef2038533da814965220f88f77d60dfa0f32685f80ead65e501337da7f SDL2-$SDL2.tar.gz
|
||||
11749926914fd488e08e744538f19329332487a6243eec39ef3c63efa154a578 harfbuzz-$HARFBUZZ.tar.gz
|
||||
926485350139ffb51ef69760db35f78846c805fef3d59bfdcb2fba704663f370 libpng-$LIBPNG.tar.xz
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9509d878ba788271c8b5abca9cfde1720f075335686237b7e9a9e7210fe67c1b libzip-$LIBZIP.tar.xz
|
||||
13388fabb361de768ecdf2b65e52bb27d1054cae6ccb6942ba926e378e00db03 SDL3-$SDL3.tar.gz
|
||||
8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 zstd-$ZSTD.tar.gz
|
||||
40973d44970dbc83ef302b0609f2e74982be2d85916dd2ee7472d30678a7abe6 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
40b14562ef3bd779bc0e0418ea2ae08fa28235f8ea6e8c0cb3bce1d6ad58dcaf qtbase-everywhere-src-$QT.tar.xz
|
||||
138cc2909aa98f5ff7283e36eb3936eb5e625d3ca3b4febae2ca21d8903dd237 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
3d0de73596e36b2daa7c48d77c4426bb091752856912fba720215f756c560dd0 qtsvg-everywhere-src-$QT.tar.xz
|
||||
9d43d409be08b8681a0155a9c65114b69c9a3fc11aef6487bb7fdc5b283c432d qttools-everywhere-src-$QT.tar.xz
|
||||
635a6093e99152243b807de51077485ceadd4786d4acb135b9340b2303035a4a qttranslations-everywhere-src-$QT.tar.xz
|
||||
e1351218d270db49c3dddcba04fb2153b09731ea3fa6830e423f5952f44585be cpuinfo-$CPUINFO.tar.gz
|
||||
012043ce6d411e6e8a91fdc4e05e6bedcfa10fcb1347d3c33908f7fdd10dfe05 qtbase-everywhere-src-$QT.tar.xz
|
||||
d2a1bbb84707b8a0aec29227b170be00f04383fbf2361943596d09e7e443c8e1 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
aa2579f21ca66d19cbcf31d87e9067e07932635d36869c8239d4decd0a9dc1fa qtsvg-everywhere-src-$QT.tar.xz
|
||||
326381b7d43f07913612f291abc298ae79bd95382e2233abce982cff2b53d2c0 qttools-everywhere-src-$QT.tar.xz
|
||||
d2106e8a580bfd77702c4c1840299288d344902b0e2c758ca813ea04c6d6a3d1 qttranslations-everywhere-src-$QT.tar.xz
|
||||
b60832071919220d2fe692151fb420fa9ea489aa4c7a2eb0e01c830cbe469858 cpuinfo-$CPUINFO.tar.gz
|
||||
3eea5ccce6670c126282f1ba4d32c19d486db49a1a5cbfb8d6f48774784d310c discord-rpc-$DISCORD_RPC.tar.gz
|
||||
3998b024b0d442614a9ee270e76e018bb37a17b8c6941212171731123cbbcac7 lunasvg-$LUNASVG.tar.gz
|
||||
3826d86f8a13564be1c047ac105041a3c5d0dc0bf826fe47cc582fe17a2ce7b1 shaderc-$SHADERC.tar.gz
|
||||
d1ef912c27e06307f2b2a5b6386070d0b8fae2bb5851f50841df7b73dcf5abdf shaderc-$SHADERC.tar.gz
|
||||
fe45c2af99f6102d2704277d392c1c83b55180a70bfd17fb888cc84a54b70573 soundtouch-$SOUNDTOUCH.tar.gz
|
||||
EOF
|
||||
|
||||
|
@ -109,7 +109,7 @@ curl -L \
|
|||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://github.com/nih-at/libzip/releases/download/v$LIBZIP/libzip-$LIBZIP.tar.xz" \
|
||||
-O "https://github.com/libsdl-org/SDL/releases/download/release-$SDL2/SDL2-$SDL2.tar.gz" \
|
||||
-O "https://github.com/libsdl-org/SDL/releases/download/release-$SDL3/SDL3-$SDL3.tar.gz" \
|
||||
-O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
|
||||
|
@ -222,11 +222,11 @@ cmake --build build --parallel
|
|||
cmake --install build
|
||||
cd ..
|
||||
|
||||
echo "Installing SDL2..."
|
||||
rm -fr "SDL2-$SDL2"
|
||||
tar xf "SDL2-$SDL2.tar.gz"
|
||||
cd "SDL2-$SDL2"
|
||||
cmake -B build "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DSDL_X11=OFF -DBUILD_SHARED_LIBS=ON
|
||||
echo "Installing SDL..."
|
||||
rm -fr "SDL3-$SDL3"
|
||||
tar xf "SDL3-$SDL3.tar.gz"
|
||||
cd "SDL3-$SDL3"
|
||||
cmake -B build "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -DSDL_X11=OFF -DBUILD_SHARED_LIBS=ON
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
rem SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
rem SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
echo Setting environment...
|
||||
|
@ -46,47 +46,46 @@ echo INSTALLDIR=%INSTALLDIR%
|
|||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.1.0
|
||||
set LIBJPEGTURBO=3.0.4
|
||||
set LIBPNG=1644
|
||||
set QT=6.8.1
|
||||
set HARFBUZZ=10.2.0
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1645
|
||||
set QT=6.8.2
|
||||
set QTMINOR=6.8
|
||||
set SDL2=2.30.11
|
||||
set WEBP=1.4.0
|
||||
set LIBZIP=1.11.2
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set SDL3=3.2.8
|
||||
set WEBP=1.5.0
|
||||
set LIBZIP=1.11.3
|
||||
set ZLIBNG=2.2.4
|
||||
set ZSTD=1.5.6
|
||||
|
||||
set CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
set CPUINFO=3ebbfd45645650c4940bf0f3b4d25ab913466bb0
|
||||
set DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
set LUNASVG=9af1ac7b90658a279b372add52d6f77a4ebb482c
|
||||
set SHADERC=1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6
|
||||
set SHADERC=fc65b19d2098cf81e55b4edc10adad2ad8268361
|
||||
set SOUNDTOUCH=463ade388f3a51da078dc9ed062bf28e4ba29da7
|
||||
set SPIRV_CROSS=vulkan-sdk-1.3.290.0
|
||||
set SPIRV_CROSS=vulkan-sdk-1.4.304.0
|
||||
set DXCOMPILER=1.8.2407.12
|
||||
set DXAGILITY=1.614.1
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" "https://download.savannah.gnu.org/releases/freetype/freetype-%FREETYPE%.tar.gz" 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" f93ff7ec6f2fcb9242256976a7e6d1da2588b5e57a559fb71a025b74bd1f5539 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" "https://download.sourceforge.net/libpng/lpng%LIBPNG%.zip" 7d7571a1faa1898b69888716dfdea0e4d466f1a5cf518e6aa626df2242bbadbe || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b || goto error
|
||||
call :downloadfile "SDL2-%SDL2%.zip" "https://github.com/libsdl-org/SDL/releases/download/release-%SDL2%/SDL2-%SDL2%.zip" a0b3e7ac5f708042683ff0f22e069bdf75563540c615f9854ecc9bc8913e2488 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" e22d997bd15b795a176c8da62c8c1da0a674eb534e02f7c01ca507bf11bce0c3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 247a0a58039275a5a4fb499a600a90f66dc6e00321bb6f86a9b8d8020344d853 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 57bd332e5550ff70a852560c591b786b6ba587c5e41cb5ef91038d82db137ab9 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c65a89140f5d68137ffec67d631ec97002fb37077d9b4eb4ee45cbec39b1c38a || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 30a8e7773e1f274557e049a97f158b808f344247da03ae5240e4956c81d51cd5 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" 6b2a43837005e1c23fdfee532b78f806863e412d2089b9c42b49ab08cbcd7665 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" 180cec309e817ec50953cd4d4208025c1931203231cf455418b0dd4021091951 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" "https://download.sourceforge.net/libpng/lpng%LIBPNG%.zip" a66c4b1350b67776e90263e2550933067cd9ccbd318db489f84dcc0d2b033249 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "SDL3-%SDL3%.zip" "https://github.com/libsdl-org/SDL/releases/download/release-%SDL3%/SDL3-%SDL3%.zip" 7f8ff5c8246db4145301bc122601a5f8cef25ee2c326eddb3e88668849c61ddf || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 44087aec0caa4aa81437e787917d29d97536484a682a5d51ec035878e57c0b5c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 83c72b5dfad04854acf61d592e3f9cdc2ed894779aab8d0470d966715266caaf || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 144d55e4d199793a76c53f19872633a79aec0314039f6f99b6a10b5be7a78fbf || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 102539447c1c76d206f24bcca2c911270cf53991548d9c3d7d0d01855f651e3b || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 33ccac9f99a357ffd83cb2d7179a0c0ffcba85a14d23d86619d5dc9721ded42f || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" 76653f135dde3036036c500e11861648ffbf9e1fc5b233ff473c60897d9db0ea || goto error
|
||||
call :downloadfile "zlib-ng-%ZLIBNG%.zip" "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/%ZLIBNG%.zip" 5e78f0ebbe507fe294bf756c741a8af4766d3838c54460a087e906b3f20346e4 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 3b1c3b46e416d36931efd34663122d7f51b550c87f74de2d38249516fe7d8be5 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 8df152f4969b308546306c074628de761f0b80265de7de534e3822fab22d7535 || goto error
|
||||
|
||||
call :downloadfile "cpuinfo-%CPUINFO%.zip" "https://github.com/pytorch/cpuinfo/archive/%CPUINFO%.zip" 13146ae7983d767a678dd01b0d6af591e77cec82babd41264b9164ab808d7d41 || goto error
|
||||
call :downloadfile "cpuinfo-%CPUINFO%.zip" "https://github.com/stenzek/cpuinfo/archive/%CPUINFO%.zip" 3430f8bae57623347b2b30a8ff041b0288f90ad99b4c2487c3d520863ce4a4e3 || goto error
|
||||
call :downloadfile "discord-rpc-%DISCORD_RPC%.zip" "https://github.com/stenzek/discord-rpc/archive/%DISCORD_RPC%.zip" 61e185e75d37b360c314125bcdf4697192d15e2d5209db3306ed6cd736d508b3 || goto error
|
||||
call :downloadfile "lunasvg-%LUNASVG%.zip" "https://github.com/stenzek/lunasvg/archive/%LUNASVG%.zip" 1425ec2bda0228b73ffdc70b0dc666fc7d2b69c33eec75a35c4421157c0e220c || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/stenzek/shaderc/archive/%SHADERC%.zip" c62c4a358a01cd8390246d4e0d35a5abe0a145a64b4f63861afbfc0fc4216d03 || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/stenzek/shaderc/archive/%SHADERC%.zip" e7766c54f289e89fc36ca4273693e6549024b5e540d7b46745cee2c61def5e4c || goto error
|
||||
call :downloadfile "soundtouch-%SOUNDTOUCH%.zip" "https://github.com/stenzek/soundtouch/archive/%SOUNDTOUCH%.zip" 107a1941181a69abe28018b9ad26fc0218625758ac193bc979abc9e26b7c0c3a || goto error
|
||||
call :downloadfile "dxcompiler-%DXCOMPILER%.zip" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.DXC/%DXCOMPILER%" eb4f6a3bb6b08aaa62f435b3dbf26b180702ca52398d3650d0dd538f56742cdc || goto error
|
||||
call :downloadfile "dxagility-%DXAGILITY%.zip" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%DXAGILITY%" 9880aa91602dd51dd6cf7911a2bca7a2323513b15338573cde014b3356eeaff2 || goto error
|
||||
|
@ -104,11 +103,12 @@ if %DEBUG%==1 (
|
|||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG"
|
||||
set ARM64TOOLCHAIN=-DCMAKE_TOOLCHAIN_FILE="%SCRIPTDIR%\cmake-toolchain-windows-arm64.cmake"
|
||||
|
||||
echo Building Zlib...
|
||||
rmdir /S /Q "zlib-%ZLIB%"
|
||||
%SEVENZIP% x "zlib%ZLIBSHORT%.zip" || goto error
|
||||
cd "zlib-%ZLIB%" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DZLIB_BUILD_EXAMPLES=OFF -B build -G Ninja || goto error
|
||||
echo Building zlib-ng...
|
||||
rmdir /S /Q "zlib-ng-%ZLIBNG%"
|
||||
%SEVENZIP% x "zlib-ng-%ZLIBNG%.zip" || goto error
|
||||
cd "zlib-ng-%ZLIBNG%" || goto error
|
||||
rem BUILD_SHARED_LIBS deliberately ommitted so that both shared and static libraries are built, we need static for the updater.
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DZLIB_COMPAT=ON -DZLIBNG_ENABLE_TESTS=OFF -DZLIB_ENABLE_TESTS=OFF -DWITH_GTEST=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
@ -186,14 +186,14 @@ cmake --build build --parallel || goto error
|
|||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building SDL2...
|
||||
rmdir /S /Q "SDL2-%SDL2%"
|
||||
%SEVENZIP% x "SDL2-%SDL2%.zip" || goto error
|
||||
cd "SDL2-%SDL2%" || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja || goto error
|
||||
echo Building SDL...
|
||||
rmdir /S /Q "SDL3-%SDL3%"
|
||||
%SEVENZIP% x "SDL3-%SDL3%.zip" || goto error
|
||||
cd "SDL3-%SDL3%" || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
copy build\SDL2.pdb "%INSTALLDIR%\bin" || goto error
|
||||
copy build\SDL3.pdb "%INSTALLDIR%\bin" || goto error
|
||||
cd .. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
rem SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
rem SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
echo Setting environment...
|
||||
|
@ -44,47 +44,46 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
|||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.1.0
|
||||
set LIBJPEGTURBO=3.0.4
|
||||
set LIBPNG=1644
|
||||
set QT=6.8.1
|
||||
set HARFBUZZ=10.2.0
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1645
|
||||
set QT=6.8.2
|
||||
set QTMINOR=6.8
|
||||
set SDL2=2.30.11
|
||||
set WEBP=1.4.0
|
||||
set LIBZIP=1.11.2
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set SDL3=3.2.8
|
||||
set WEBP=1.5.0
|
||||
set LIBZIP=1.11.3
|
||||
set ZLIBNG=2.2.4
|
||||
set ZSTD=1.5.6
|
||||
|
||||
set CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
set CPUINFO=3ebbfd45645650c4940bf0f3b4d25ab913466bb0
|
||||
set DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
set LUNASVG=9af1ac7b90658a279b372add52d6f77a4ebb482c
|
||||
set SHADERC=1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6
|
||||
set SHADERC=fc65b19d2098cf81e55b4edc10adad2ad8268361
|
||||
set SOUNDTOUCH=463ade388f3a51da078dc9ed062bf28e4ba29da7
|
||||
set SPIRV_CROSS=vulkan-sdk-1.3.290.0
|
||||
set SPIRV_CROSS=vulkan-sdk-1.4.304.0
|
||||
set DXCOMPILER=1.8.2407.12
|
||||
set DXAGILITY=1.614.1
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" "https://download.savannah.gnu.org/releases/freetype/freetype-%FREETYPE%.tar.gz" 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" f93ff7ec6f2fcb9242256976a7e6d1da2588b5e57a559fb71a025b74bd1f5539 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" "https://download.sourceforge.net/libpng/lpng%LIBPNG%.zip" 7d7571a1faa1898b69888716dfdea0e4d466f1a5cf518e6aa626df2242bbadbe || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b || goto error
|
||||
call :downloadfile "SDL2-%SDL2%.zip" "https://github.com/libsdl-org/SDL/releases/download/release-%SDL2%/SDL2-%SDL2%.zip" a0b3e7ac5f708042683ff0f22e069bdf75563540c615f9854ecc9bc8913e2488 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" e22d997bd15b795a176c8da62c8c1da0a674eb534e02f7c01ca507bf11bce0c3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 247a0a58039275a5a4fb499a600a90f66dc6e00321bb6f86a9b8d8020344d853 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 57bd332e5550ff70a852560c591b786b6ba587c5e41cb5ef91038d82db137ab9 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" c65a89140f5d68137ffec67d631ec97002fb37077d9b4eb4ee45cbec39b1c38a || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 30a8e7773e1f274557e049a97f158b808f344247da03ae5240e4956c81d51cd5 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" 6b2a43837005e1c23fdfee532b78f806863e412d2089b9c42b49ab08cbcd7665 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip" 180cec309e817ec50953cd4d4208025c1931203231cf455418b0dd4021091951 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" "https://download.sourceforge.net/libpng/lpng%LIBPNG%.zip" a66c4b1350b67776e90263e2550933067cd9ccbd318db489f84dcc0d2b033249 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "SDL3-%SDL3%.zip" "https://github.com/libsdl-org/SDL/releases/download/release-%SDL3%/SDL3-%SDL3%.zip" 7f8ff5c8246db4145301bc122601a5f8cef25ee2c326eddb3e88668849c61ddf || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 44087aec0caa4aa81437e787917d29d97536484a682a5d51ec035878e57c0b5c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 83c72b5dfad04854acf61d592e3f9cdc2ed894779aab8d0470d966715266caaf || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 144d55e4d199793a76c53f19872633a79aec0314039f6f99b6a10b5be7a78fbf || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 102539447c1c76d206f24bcca2c911270cf53991548d9c3d7d0d01855f651e3b || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 33ccac9f99a357ffd83cb2d7179a0c0ffcba85a14d23d86619d5dc9721ded42f || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "libzip-%LIBZIP%.tar.gz" "https://github.com/nih-at/libzip/releases/download/v%LIBZIP%/libzip-%LIBZIP%.tar.gz" 76653f135dde3036036c500e11861648ffbf9e1fc5b233ff473c60897d9db0ea || goto error
|
||||
call :downloadfile "zlib-ng-%ZLIBNG%.zip" "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/%ZLIBNG%.zip" 5e78f0ebbe507fe294bf756c741a8af4766d3838c54460a087e906b3f20346e4 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 3b1c3b46e416d36931efd34663122d7f51b550c87f74de2d38249516fe7d8be5 || goto error
|
||||
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 8df152f4969b308546306c074628de761f0b80265de7de534e3822fab22d7535 || goto error
|
||||
|
||||
call :downloadfile "cpuinfo-%CPUINFO%.zip" "https://github.com/pytorch/cpuinfo/archive/%CPUINFO%.zip" 13146ae7983d767a678dd01b0d6af591e77cec82babd41264b9164ab808d7d41 || goto error
|
||||
call :downloadfile "cpuinfo-%CPUINFO%.zip" "https://github.com/stenzek/cpuinfo/archive/%CPUINFO%.zip" 3430f8bae57623347b2b30a8ff041b0288f90ad99b4c2487c3d520863ce4a4e3 || goto error
|
||||
call :downloadfile "discord-rpc-%DISCORD_RPC%.zip" "https://github.com/stenzek/discord-rpc/archive/%DISCORD_RPC%.zip" 61e185e75d37b360c314125bcdf4697192d15e2d5209db3306ed6cd736d508b3 || goto error
|
||||
call :downloadfile "lunasvg-%LUNASVG%.zip" "https://github.com/stenzek/lunasvg/archive/%LUNASVG%.zip" 1425ec2bda0228b73ffdc70b0dc666fc7d2b69c33eec75a35c4421157c0e220c || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/stenzek/shaderc/archive/%SHADERC%.zip" c62c4a358a01cd8390246d4e0d35a5abe0a145a64b4f63861afbfc0fc4216d03 || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/stenzek/shaderc/archive/%SHADERC%.zip" e7766c54f289e89fc36ca4273693e6549024b5e540d7b46745cee2c61def5e4c || goto error
|
||||
call :downloadfile "soundtouch-%SOUNDTOUCH%.zip" "https://github.com/stenzek/soundtouch/archive/%SOUNDTOUCH%.zip" 107a1941181a69abe28018b9ad26fc0218625758ac193bc979abc9e26b7c0c3a || goto error
|
||||
call :downloadfile "dxcompiler-%DXCOMPILER%.zip" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.DXC/%DXCOMPILER%" eb4f6a3bb6b08aaa62f435b3dbf26b180702ca52398d3650d0dd538f56742cdc || goto error
|
||||
call :downloadfile "dxagility-%DXAGILITY%.zip" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%DXAGILITY%" 9880aa91602dd51dd6cf7911a2bca7a2323513b15338573cde014b3356eeaff2 || goto error
|
||||
|
@ -101,11 +100,12 @@ if %DEBUG%==1 (
|
|||
|
||||
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG"
|
||||
|
||||
echo Building Zlib...
|
||||
rmdir /S /Q "zlib-%ZLIB%"
|
||||
%SEVENZIP% x "zlib%ZLIBSHORT%.zip" || goto error
|
||||
cd "zlib-%ZLIB%" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DZLIB_BUILD_EXAMPLES=OFF -B build -G Ninja || goto error
|
||||
echo Building zlib-ng...
|
||||
rmdir /S /Q "zlib-ng-%ZLIBNG%"
|
||||
%SEVENZIP% x "zlib-ng-%ZLIBNG%.zip" || goto error
|
||||
cd "zlib-ng-%ZLIBNG%" || goto error
|
||||
rem BUILD_SHARED_LIBS deliberately ommitted so that both shared and static libraries are built, we need static for the updater.
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DZLIB_COMPAT=ON -DZLIBNG_ENABLE_TESTS=OFF -DZLIB_ENABLE_TESTS=OFF -DWITH_GTEST=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
@ -184,13 +184,13 @@ ninja -C build install || goto error
|
|||
cd .. || goto error
|
||||
|
||||
echo Building SDL...
|
||||
rmdir /S /Q "SDL2-%SDL2%"
|
||||
%SEVENZIP% x "SDL2-%SDL2%.zip" || goto error
|
||||
cd "SDL2-%SDL2%" || goto error
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -G Ninja || goto error
|
||||
rmdir /S /Q "SDL3-%SDL3%"
|
||||
%SEVENZIP% x "SDL3-%SDL3%.zip" || goto error
|
||||
cd "SDL3-%SDL3%" || goto error
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release %FORCEPDB% -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
copy build\SDL2.pdb "%INSTALLDIR%\bin" || goto error
|
||||
copy build\SDL3.pdb "%INSTALLDIR%\bin" || goto error
|
||||
cd .. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
--- a/CMakeLists.txt 2024-12-29 21:34:43.219279282 +1000
|
||||
+++ b/CMakeLists.txt 2024-12-29 21:34:59.495612349 +1000
|
||||
@@ -3047,10 +3047,6 @@
|
||||
listtostr(EXTRA_CFLAGS _EXTRA_CFLAGS)
|
||||
set(EXTRA_CFLAGS ${_EXTRA_CFLAGS})
|
||||
|
||||
-if(USE_GCC OR USE_CLANG)
|
||||
- string(REGEX REPLACE "(^| )-I" "\\1 -isystem" EXTRA_CFLAGS "${EXTRA_CFLAGS}")
|
||||
-endif()
|
||||
-
|
||||
# Compat helpers for the configuration files
|
||||
|
||||
if(EXISTS "${PROJECT_SOURCE_DIR}/VERSION.txt")
|
54
scripts/generate_achievement_hash_database.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from importlib.machinery import FileFinder
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print(f"Syntax: {sys.argv[0]} WEB-API-KEY OUTPUT_FILE.yaml")
|
||||
sys.exit(1)
|
||||
|
||||
print("Sending request...")
|
||||
url = "https://retroachievements.org/API/API_GetGameList.php?y=" + sys.argv[1] + "&i=12&h=1&f=0"
|
||||
req = urllib.request.Request(url)
|
||||
req.add_header("User-Agent", "curl/8.10.1") # CF blocks urllib user agent
|
||||
data = None
|
||||
with urllib.request.urlopen(req) as response:
|
||||
data = response.read().decode('utf-8')
|
||||
|
||||
data = json.loads(data)
|
||||
print(f"Found {len(data)} entries in JSON")
|
||||
|
||||
games = {}
|
||||
hashes = {}
|
||||
for entry in data:
|
||||
if ("ID" not in entry or \
|
||||
"NumAchievements" not in entry or \
|
||||
"Hashes" not in entry or \
|
||||
len(entry["Hashes"]) == 0):
|
||||
continue
|
||||
|
||||
game_id = int(entry["ID"])
|
||||
num_achievements = int(entry["NumAchievements"])
|
||||
|
||||
if game_id not in games:
|
||||
games[game_id] = num_achievements
|
||||
else:
|
||||
print(f"Duplicate game {game_id}")
|
||||
|
||||
for thash in entry["Hashes"]:
|
||||
if thash in hashes:
|
||||
print(f"Duplicate hash {thash}")
|
||||
continue
|
||||
hashes[thash] = game_id
|
||||
|
||||
print(f"Extracted {len(games)} games")
|
||||
print(f"Extracted {len(hashes)} hashes")
|
||||
|
||||
with open(sys.argv[2], "w") as f:
|
||||
f.write("hashes:\n")
|
||||
for ghash, game_id in hashes.items():
|
||||
f.write(f" {ghash}: {game_id}\n")
|
||||
|
||||
f.write("achievements:\n")
|
||||
for game_id, num_achievements in games.items():
|
||||
f.write(f" {game_id}: {num_achievements}\n")
|
|
@ -1,9 +0,0 @@
|
|||
if [[ -z "$I_WANT_A_BROKEN_WAYLAND_UI" ]]; then
|
||||
echo "Forcing X11 instead of Wayland, due to various protocol limitations"
|
||||
echo "and Qt issues. If you want to use Wayland, launch DuckStation with"
|
||||
echo "I_WANT_A_BROKEN_WAYLAND_UI=YES set."
|
||||
export QT_QPA_PLATFORM=xcb
|
||||
else
|
||||
echo "Wayland is not being disabled. Do not complain when things break."
|
||||
fi
|
||||
|
|
@ -18,9 +18,9 @@ function retry_command {
|
|||
|
||||
this_dir="$(readlink -f "$(dirname "$0")")"
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
if [ "$#" -ne 4 ]; then
|
||||
echo "Syntax: $0 <path to AppDir> <.deb arch> <triple> <ubuntu mirror> <binary to run>"
|
||||
echo "e.g. $0 DuckStation.AppDir amd64 x86_64-linux-gnu https://archive.ubuntu.com/ubuntu/ duckstation-qt"
|
||||
echo "e.g. $0 DuckStation.AppDir amd64 x86_64-linux-gnu duckstation-qt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -28,22 +28,26 @@ fi
|
|||
APPDIR=$1
|
||||
DEBARCH=$2
|
||||
TRIPLE=$3
|
||||
MIRROR=$4
|
||||
APPNAME=$5
|
||||
APPNAME=$4
|
||||
|
||||
LIBC_PACKAGE_URL="${MIRROR}/pool/main/g/glibc/libc6_2.35-0ubuntu3.8_${DEBARCH}.deb"
|
||||
LIBGCCS_PACKAGE_URL="${MIRROR}/pool/main/g/gcc-12/libgcc-s1_12.3.0-1ubuntu1~22.04_${DEBARCH}.deb"
|
||||
LIBSTDCXX_PACKAGE_URL="${MIRROR}/pool/main/g/gcc-12/libstdc++6_12.3.0-1ubuntu1~22.04_${DEBARCH}.deb"
|
||||
GLIBC_VERSION=2.35
|
||||
|
||||
if [ ! -f "libc.deb" ]; then
|
||||
retry_command wget -O "libc.deb" "https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/libc6_2.35-0ubuntu3.9_${DEBARCH}.deb"
|
||||
fi
|
||||
if [ ! -f "libgccs.deb" ]; then
|
||||
retry_command wget -O "libgccs.deb" "https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/libgcc-s1_12.3.0-1ubuntu1.22.04_${DEBARCH}.deb"
|
||||
fi
|
||||
if [ ! -f "libstdc++.deb" ]; then
|
||||
retry_command wget -O "libstdc++.deb" "https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/libstdc++6_12.3.0-1ubuntu1.22.04_${DEBARCH}.deb"
|
||||
fi
|
||||
|
||||
rm -fr "temp"
|
||||
mkdir "temp"
|
||||
cd "temp"
|
||||
retry_command wget -O "libc.deb" "${LIBC_PACKAGE_URL}"
|
||||
retry_command wget -O "libgccs.deb" "${LIBGCCS_PACKAGE_URL}"
|
||||
retry_command wget -O "libstdc++.deb" "${LIBSTDCXX_PACKAGE_URL}"
|
||||
dpkg -x "libc.deb" .
|
||||
dpkg -x "libgccs.deb" .
|
||||
dpkg -x "libstdc++.deb" .
|
||||
dpkg -x "../libc.deb" .
|
||||
dpkg -x "../libgccs.deb" .
|
||||
dpkg -x "../libstdc++.deb" .
|
||||
|
||||
# Copy everything into AppDir
|
||||
RUNTIME="${APPDIR}/libc-runtime"
|
||||
|
|
|
@ -16,13 +16,13 @@ function retry_command {
|
|||
|
||||
# Workaround for https://github.com/actions/runner-images/issues/675
|
||||
retry_command wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
retry_command sudo apt-add-repository -n 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main'
|
||||
retry_command sudo apt-add-repository -n 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main'
|
||||
|
||||
retry_command sudo apt-get update
|
||||
retry_command sudo apt-get -y install \
|
||||
build-essential clang-18 cmake curl extra-cmake-modules git libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdecor-0-dev libegl-dev libevdev-dev \
|
||||
build-essential clang-19 cmake curl extra-cmake-modules git libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdecor-0-dev libegl-dev libevdev-dev \
|
||||
libfontconfig-dev libfreetype-dev libfuse2 libgtk-3-dev libgudev-1.0-dev libharfbuzz-dev libinput-dev libopengl-dev libpipewire-0.3-dev libpulse-dev \
|
||||
libssl-dev libudev-dev libva-dev libwayland-dev libx11-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev \
|
||||
libxcb-glx0-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev \
|
||||
libxcb-shape0-dev libxcb-shm0-dev libxcb-sync-dev libxcb-util-dev libxcb-xfixes0-dev libxcb-xinput-dev libxcb-xkb-dev libxext-dev libxkbcommon-x11-dev \
|
||||
libxrandr-dev lld-18 llvm-18 nasm ninja-build patchelf pkg-config zlib1g-dev
|
||||
libxrandr-dev lld-19 llvm-19 nasm ninja-build patchelf pkg-config zlib1g-dev
|
||||
|
|
|
@ -34,6 +34,7 @@ APPDIRNAME=DuckStation.AppDir
|
|||
STRIP=strip
|
||||
|
||||
declare -a MANUAL_LIBS=(
|
||||
"libz.so.1"
|
||||
"libavcodec.so.61"
|
||||
"libavformat.so.61"
|
||||
"libavutil.so.59"
|
||||
|
@ -185,15 +186,6 @@ echo "Generating AppStream metainfo..."
|
|||
mkdir -p "$OUTDIR/usr/share/metainfo"
|
||||
"$SCRIPTDIR/../generate-metainfo.sh" "$OUTDIR/usr/share/metainfo"
|
||||
|
||||
# Copy in AppRun hooks.
|
||||
echo "Copying AppRun hooks..."
|
||||
mkdir -p "$OUTDIR/apprun-hooks"
|
||||
for hookpath in "$SCRIPTDIR/apprun-hooks"/*; do
|
||||
hookname=$(basename "$hookpath")
|
||||
cp -v "$hookpath" "$OUTDIR/apprun-hooks/$hookname"
|
||||
sed -i -e 's/exec /source "$this_dir"\/apprun-hooks\/"'"$hookname"'"\nexec /' "$OUTDIR/AppRun"
|
||||
done
|
||||
|
||||
echo "Generating AppImage..."
|
||||
rm -f "$NAME.AppImage"
|
||||
"$APPIMAGETOOL" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$NAME.AppImage"
|
||||
|
|
|
@ -26,111 +26,74 @@ if [ "$1" == "-inject-libc" ]; then
|
|||
fi
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
echo "Syntax: $0 [-inject-libc] <target arch> <path to build directory> <deps prefix> <chroot dir> <output name>"
|
||||
echo "Syntax: $0 [-inject-libc] <duckstation-qt|duckstation-mini> <target arch> <path to build directory> <deps prefix> <chroot dir>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ARCH=$1
|
||||
BUILDDIR=$2
|
||||
DEPSDIR=$3
|
||||
CHROOTDIR=$4
|
||||
NAME=$5
|
||||
BINARY=$1
|
||||
ARCH=$2
|
||||
BUILDDIR=$3
|
||||
DEPSDIR=$4
|
||||
CHROOTDIR=$5
|
||||
|
||||
BINARY=duckstation-qt
|
||||
APPDIRNAME=DuckStation.AppDir
|
||||
STRIP=llvm-strip
|
||||
TRIPLE="${ARCH}-linux-gnu"
|
||||
|
||||
if [ "$ARCH" == "arm64" ]; then
|
||||
DEBARCH="arm64"
|
||||
RUNTIMEARCH="aarch64"
|
||||
TRIPLE="aarch64-linux-gnu"
|
||||
elif [ "$ARCH" == "armhf" ]; then
|
||||
DEBARCH="armhf"
|
||||
RUNTIMEARCH="armhf"
|
||||
TRIPLE="arm-linux-gnueabihf"
|
||||
else
|
||||
echo "Unknown arch ${ARCH}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$BINARY" == "duckstation-qt" ]; then
|
||||
echo "Building Qt AppImage."
|
||||
ADD_QT_LIBS=true
|
||||
APPIMAGENAME="DuckStation-${ARCH}"
|
||||
elif [ "$BINARY" == "duckstation-mini" ]; then
|
||||
echo "Building Mini AppImage."
|
||||
ADD_QT_LIBS=false
|
||||
APPIMAGENAME="DuckStation-Mini-${ARCH}"
|
||||
else
|
||||
echo "Unknown binary $BINARY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APPDIRNAME="${APPIMAGENAME}.AppDir"
|
||||
|
||||
declare -a SYSLIBS=(
|
||||
"libatk-1.0.so.0"
|
||||
"libatk-bridge-2.0.so.0"
|
||||
"libatspi.so.0"
|
||||
"libblkid.so.1"
|
||||
"libbrotlicommon.so.1"
|
||||
"libbrotlidec.so.1"
|
||||
"libbsd.so.0"
|
||||
"libcairo-gobject.so.2"
|
||||
"libcairo.so.2"
|
||||
"libcap.so.2"
|
||||
"libcrypto.so.3"
|
||||
"libcurl.so.4"
|
||||
"libdatrie.so.1"
|
||||
"libdbus-1.so.3"
|
||||
"libdeflate.so.0"
|
||||
"libepoxy.so.0"
|
||||
"libffi.so.8"
|
||||
"libgcrypt.so.20"
|
||||
"libgdk-3.so.0"
|
||||
"libgdk_pixbuf-2.0.so.0"
|
||||
"libgio-2.0.so.0"
|
||||
"libglib-2.0.so.0"
|
||||
"libgmodule-2.0.so.0"
|
||||
"libgnutls.so.30"
|
||||
"libgobject-2.0.so.0"
|
||||
"libgraphite2.so.3"
|
||||
"libgssapi_krb5.so.2"
|
||||
"libgtk-3.so.0"
|
||||
"libhogweed.so.6"
|
||||
"libidn2.so.0"
|
||||
"libjbig.so.0"
|
||||
"libk5crypto.so.3"
|
||||
"libkeyutils.so.1"
|
||||
"libkrb5.so.3"
|
||||
"libkrb5support.so.0"
|
||||
"liblber-2.5.so.0"
|
||||
"libldap-2.5.so.0"
|
||||
"liblz4.so.1"
|
||||
"liblzma.so.5"
|
||||
"libmd.so.0"
|
||||
"libmount.so.1"
|
||||
"libnettle.so.8"
|
||||
"libnghttp2.so.14"
|
||||
"libp11-kit.so.0"
|
||||
"libpango-1.0.so.0"
|
||||
"libpangocairo-1.0.so.0"
|
||||
"libpangoft2-1.0.so.0"
|
||||
"libpcre2-16.so.0"
|
||||
"libpcre2-8.so.0"
|
||||
"libpcre.so.3"
|
||||
"libpixman-1.so.0"
|
||||
"libpsl.so.5"
|
||||
"librtmp.so.1"
|
||||
"libsasl2.so.2"
|
||||
"libselinux.so.1"
|
||||
"libssh.so.4"
|
||||
"libssl.so.3"
|
||||
"libsystemd.so.0"
|
||||
"libtasn1.so.6"
|
||||
"libtiff.so.5"
|
||||
"libudev.so.1"
|
||||
"libunistring.so.2"
|
||||
"libXau.so.6"
|
||||
"libxcb-cursor.so.0"
|
||||
"libxcb-glx.so.0"
|
||||
"libxcb-icccm.so.4"
|
||||
"libxcb-image.so.0"
|
||||
"libxcb-keysyms.so.1"
|
||||
"libxcb-randr.so.0"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-render-util.so.0"
|
||||
"libxcb-shape.so.0"
|
||||
"libxcb-shm.so.0"
|
||||
"libxcb-sync.so.1"
|
||||
"libxcb-util.so.1"
|
||||
"libxcb-xfixes.so.0"
|
||||
"libxcb-xkb.so.1"
|
||||
"libXcomposite.so.1"
|
||||
"libXcursor.so.1"
|
||||
"libXdamage.so.1"
|
||||
"libXdmcp.so.6"
|
||||
"libXext.so.6"
|
||||
"libXfixes.so.3"
|
||||
"libXinerama.so.1"
|
||||
"libXi.so.6"
|
||||
"libxkbcommon.so.0"
|
||||
"libxkbcommon-x11.so.0"
|
||||
"libXrandr.so.2"
|
||||
"libXrender.so.1"
|
||||
)
|
||||
|
||||
declare -a DEPLIBS=(
|
||||
|
@ -139,7 +102,7 @@ declare -a DEPLIBS=(
|
|||
"libharfbuzz.so"
|
||||
"libjpeg.so.62"
|
||||
"libpng16.so.16"
|
||||
"libSDL2-2.0.so.0"
|
||||
"libSDL3.so.0"
|
||||
"libsharpyuv.so.0"
|
||||
"libwebpdemux.so.2"
|
||||
"libwebpmux.so.3"
|
||||
|
@ -163,36 +126,103 @@ declare -a DEPLIBS=(
|
|||
#"libva.so.2"
|
||||
)
|
||||
|
||||
declare -a QTLIBS=(
|
||||
"libQt6Core.so.6"
|
||||
"libQt6DBus.so.6"
|
||||
"libQt6Gui.so.6"
|
||||
"libQt6OpenGL.so.6"
|
||||
"libQt6Svg.so.6"
|
||||
"libQt6WaylandClient.so.6"
|
||||
"libQt6WaylandEglClientHwIntegration.so.6"
|
||||
"libQt6Widgets.so.6"
|
||||
"libQt6XcbQpa.so.6"
|
||||
)
|
||||
if [ "${ADD_QT_LIBS}" == true ]; then
|
||||
SYSLIBS+=(
|
||||
"libatk-1.0.so.0"
|
||||
"libatk-bridge-2.0.so.0"
|
||||
"libatspi.so.0"
|
||||
"libblkid.so.1"
|
||||
"libcairo-gobject.so.2"
|
||||
"libcairo.so.2"
|
||||
"libcap.so.2"
|
||||
"libdatrie.so.1"
|
||||
"libdeflate.so.0"
|
||||
"libdbus-1.so.3"
|
||||
"libepoxy.so.0"
|
||||
"libgcrypt.so.20"
|
||||
"libgdk-3.so.0"
|
||||
"libgdk_pixbuf-2.0.so.0"
|
||||
"libgio-2.0.so.0"
|
||||
"libglib-2.0.so.0"
|
||||
"libgmodule-2.0.so.0"
|
||||
"libgobject-2.0.so.0"
|
||||
"libgraphite2.so.3"
|
||||
"libgtk-3.so.0"
|
||||
"libjbig.so.0"
|
||||
"liblz4.so.1"
|
||||
"liblzma.so.5"
|
||||
"libmd.so.0"
|
||||
"libmount.so.1"
|
||||
"libpango-1.0.so.0"
|
||||
"libpangocairo-1.0.so.0"
|
||||
"libpangoft2-1.0.so.0"
|
||||
"libpcre2-16.so.0"
|
||||
"libpcre2-8.so.0"
|
||||
"libpcre.so.3"
|
||||
"libpixman-1.so.0"
|
||||
"libselinux.so.1"
|
||||
"libsystemd.so.0"
|
||||
"libtiff.so.5"
|
||||
"libXau.so.6"
|
||||
"libxcb-cursor.so.0"
|
||||
"libxcb-glx.so.0"
|
||||
"libxcb-icccm.so.4"
|
||||
"libxcb-image.so.0"
|
||||
"libxcb-keysyms.so.1"
|
||||
"libxcb-randr.so.0"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-render-util.so.0"
|
||||
"libxcb-shape.so.0"
|
||||
"libxcb-shm.so.0"
|
||||
"libxcb-sync.so.1"
|
||||
"libxcb-util.so.1"
|
||||
"libxcb-xfixes.so.0"
|
||||
"libxcb-xkb.so.1"
|
||||
"libXcomposite.so.1"
|
||||
"libXcursor.so.1"
|
||||
"libXdamage.so.1"
|
||||
"libXdmcp.so.6"
|
||||
"libXext.so.6"
|
||||
"libXfixes.so.3"
|
||||
"libXinerama.so.1"
|
||||
"libXi.so.6"
|
||||
"libxkbcommon.so.0"
|
||||
"libxkbcommon-x11.so.0"
|
||||
"libXrandr.so.2"
|
||||
"libXrender.so.1"
|
||||
)
|
||||
|
||||
declare -a QTPLUGINS=(
|
||||
"plugins/iconengines"
|
||||
"plugins/imageformats"
|
||||
"plugins/platforminputcontexts"
|
||||
"plugins/platforms"
|
||||
"plugins/platformthemes"
|
||||
"plugins/wayland-decoration-client"
|
||||
"plugins/wayland-graphics-integration-client"
|
||||
"plugins/wayland-shell-integration"
|
||||
"plugins/xcbglintegrations"
|
||||
)
|
||||
declare -a QTLIBS=(
|
||||
"libQt6Core.so.6"
|
||||
"libQt6DBus.so.6"
|
||||
"libQt6Gui.so.6"
|
||||
"libQt6OpenGL.so.6"
|
||||
"libQt6Svg.so.6"
|
||||
"libQt6WaylandClient.so.6"
|
||||
"libQt6WaylandEglClientHwIntegration.so.6"
|
||||
"libQt6Widgets.so.6"
|
||||
"libQt6XcbQpa.so.6"
|
||||
)
|
||||
|
||||
declare -a QTPLUGINS=(
|
||||
"plugins/iconengines"
|
||||
"plugins/imageformats"
|
||||
"plugins/platforminputcontexts"
|
||||
"plugins/platforms"
|
||||
"plugins/platformthemes"
|
||||
"plugins/wayland-decoration-client"
|
||||
"plugins/wayland-graphics-integration-client"
|
||||
"plugins/wayland-shell-integration"
|
||||
"plugins/xcbglintegrations"
|
||||
)
|
||||
fi
|
||||
|
||||
set -e
|
||||
IFS="
|
||||
"
|
||||
|
||||
APPIMAGETOOL=./appimagetool-x86_64
|
||||
APPIMAGERUNTIME=./runtime-${ARCH}
|
||||
APPIMAGERUNTIME=./runtime-${RUNTIMEARCH}
|
||||
PATCHELF=patchelf
|
||||
|
||||
if [ ! -f "$APPIMAGETOOL" ]; then
|
||||
|
@ -201,7 +231,7 @@ if [ ! -f "$APPIMAGETOOL" ]; then
|
|||
fi
|
||||
|
||||
if [ ! -f "$APPIMAGERUNTIME" ]; then
|
||||
retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${ARCH}
|
||||
retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${RUNTIMEARCH}
|
||||
fi
|
||||
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
|
@ -212,10 +242,6 @@ mkdir -p "$OUTDIR/usr/bin" "$OUTDIR/usr/lib"
|
|||
echo "Copying binary and resources..."
|
||||
cp -a "$BUILDDIR/bin/$BINARY" "$BUILDDIR/bin/resources" "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"
|
||||
|
||||
# Currently we leave the main binary unstripped, uncomment if this is not desired.
|
||||
# NOTE: Strip must come before patchelf, otherwise shit breaks.
|
||||
$STRIP "$OUTDIR/usr/bin/$BINARY"
|
||||
|
||||
# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.
|
||||
echo "Patching RPATH in ${BINARY}..."
|
||||
patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY"
|
||||
|
@ -238,7 +264,7 @@ for lib in "${SYSLIBS[@]}"; do
|
|||
exit 1
|
||||
fi
|
||||
|
||||
$STRIP $OUTDIR/usr/lib/$blib
|
||||
"$STRIP" $OUTDIR/usr/lib/$blib
|
||||
done
|
||||
|
||||
echo "Copying local libraries..."
|
||||
|
@ -252,28 +278,37 @@ for lib in "${DEPLIBS[@]}"; do
|
|||
exit 1
|
||||
fi
|
||||
|
||||
$STRIP "$OUTDIR/usr/lib/$blib"
|
||||
"$STRIP" "$OUTDIR/usr/lib/$blib"
|
||||
done
|
||||
|
||||
echo "Copying Qt libraries..."
|
||||
for lib in "${QTLIBS[@]}"; do
|
||||
cp -avL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib"
|
||||
$STRIP "$OUTDIR/usr/lib/$lib"
|
||||
done
|
||||
if [ "${ADD_QT_LIBS}" == true ]; then
|
||||
echo "Copying Qt libraries..."
|
||||
for lib in "${QTLIBS[@]}"; do
|
||||
cp -avL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib"
|
||||
"$STRIP" "$OUTDIR/usr/lib/$lib"
|
||||
done
|
||||
|
||||
echo "Copying Qt plugins..."
|
||||
mkdir -p $OUTDIR/usr/lib/plugins
|
||||
for plugin in "${QTPLUGINS[@]}"; do
|
||||
mkdir -p "$OUTDIR/usr/lib/$plugin"
|
||||
cp -avL "$DEPSDIR/$plugin/"*.so "$OUTDIR/usr/lib/$plugin/"
|
||||
done
|
||||
echo "Copying Qt plugins..."
|
||||
mkdir -p $OUTDIR/usr/lib/plugins
|
||||
for plugin in "${QTPLUGINS[@]}"; do
|
||||
mkdir -p "$OUTDIR/usr/lib/$plugin"
|
||||
cp -avL "$DEPSDIR/$plugin/"*.so "$OUTDIR/usr/lib/$plugin/"
|
||||
done
|
||||
|
||||
for so in $(find $OUTDIR/usr/lib/plugins -iname '*.so'); do
|
||||
# This is ../../ because it's usually plugins/group/name.so
|
||||
echo "Patching RPATH in ${so}..."
|
||||
patchelf --set-rpath '$ORIGIN/../..' "$so"
|
||||
$STRIP "$so"
|
||||
done
|
||||
for so in $(find $OUTDIR/usr/lib/plugins -iname '*.so'); do
|
||||
# This is ../../ because it's usually plugins/group/name.so
|
||||
echo "Patching RPATH in ${so}..."
|
||||
patchelf --set-rpath '$ORIGIN/../..' "$so"
|
||||
"$STRIP" "$so"
|
||||
done
|
||||
|
||||
echo "Creating qt.conf..."
|
||||
cat > "$OUTDIR/usr/bin/qt.conf" << EOF
|
||||
[Paths]
|
||||
Plugins = ../lib/plugins
|
||||
EOF
|
||||
|
||||
fi
|
||||
|
||||
for so in $(find $OUTDIR/usr/lib -maxdepth 1); do
|
||||
if [ -f "$so" ]; then
|
||||
|
@ -282,12 +317,6 @@ for so in $(find $OUTDIR/usr/lib -maxdepth 1); do
|
|||
fi
|
||||
done
|
||||
|
||||
echo "Creating qt.conf..."
|
||||
cat > "$OUTDIR/usr/bin/qt.conf" << EOF
|
||||
[Paths]
|
||||
Plugins = ../lib/plugins
|
||||
EOF
|
||||
|
||||
# Copy desktop/icon
|
||||
echo "Copying desktop/icon..."
|
||||
mkdir -p "$OUTDIR/usr/share/applications"
|
||||
|
@ -307,28 +336,15 @@ cp "$SCRIPTDIR/apprun-cross.sh" "$OUTDIR/AppRun"
|
|||
chmod +x "$OUTDIR/AppRun"
|
||||
ln -s "usr/bin/$BINARY" "$OUTDIR/AppRun.wrapped"
|
||||
|
||||
# Copy in AppRun hooks.
|
||||
echo "Copying AppRun hooks..."
|
||||
mkdir -p "$OUTDIR/apprun-hooks"
|
||||
for hookpath in "$SCRIPTDIR/apprun-hooks"/*; do
|
||||
hookname=$(basename "$hookpath")
|
||||
cp -v "$hookpath" "$OUTDIR/apprun-hooks/$hookname"
|
||||
sed -i -e 's/exec /source "$this_dir"\/apprun-hooks\/"'"$hookname"'"\nexec /' "$OUTDIR/AppRun"
|
||||
done
|
||||
|
||||
# Optionally inject libc
|
||||
if [ "$INJECT_LIBC" == true ]; then
|
||||
echo "Injecting libc/libc++..."
|
||||
if [ "$ARCH" == "aarch64" ]; then
|
||||
DEBARCH="arm64"
|
||||
else
|
||||
echo "Unknown arch for libc injection."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$SCRIPTDIR/inject-libc.sh" "$OUTDIR" "$DEBARCH" "$TRIPLE" "https://ports.ubuntu.com" "$BINARY"
|
||||
"$SCRIPTDIR/inject-libc.sh" "$OUTDIR" "$DEBARCH" "$TRIPLE" "$BINARY"
|
||||
fi
|
||||
|
||||
echo "Generating AppImage..."
|
||||
rm -f "$NAME.AppImage"
|
||||
"$APPIMAGETOOL" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$NAME.AppImage"
|
||||
rm -f "$APPIMAGENAME.AppImage"
|
||||
|
||||
# Can't run the appimage in a docker container because no fuse, so extract it first.
|
||||
"$APPIMAGETOOL" --appimage-extract
|
||||
"$PWD/squashfs-root/AppRun" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$APPIMAGENAME.AppImage"
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
# NOTE: These package files are intended for your own personal/private use.
|
||||
# You do not have permission to upload them independently to other package repositories.
|
||||
#
|
||||
# To build yourself:
|
||||
# git clone https://github.com/stenzek/duckstation.git
|
||||
# cd duckstation/scripts/packaging/arch
|
||||
# makepkg -i
|
||||
|
||||
pkgname=duckstation
|
||||
pkgver=0
|
||||
|
@ -28,9 +33,9 @@ depends=('libjpeg.so' # libjpeg or libjpeg-turbo
|
|||
'libx11'
|
||||
'libxrandr'
|
||||
'libzip'
|
||||
'qt6-base>=6.8.0'
|
||||
'qt6-imageformats>=6.8.0'
|
||||
'qt6-svg>=6.8.0'
|
||||
'qt6-base>=6.8.2'
|
||||
'qt6-imageformats>=6.8.2'
|
||||
'qt6-svg>=6.8.2'
|
||||
'wayland'
|
||||
'zlib'
|
||||
'zstd'
|
||||
|
@ -46,17 +51,26 @@ makedepends=('base-devel'
|
|||
'lld'
|
||||
'llvm'
|
||||
'ninja'
|
||||
'qt6-tools>=6.8.0')
|
||||
'qt6-tools>=6.8.2')
|
||||
|
||||
source=(
|
||||
"${pkgname}::git+file://${startdir}/../../.."
|
||||
"https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
"https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
)
|
||||
sha256sums=(
|
||||
"SKIP"
|
||||
"SKIP"
|
||||
"SKIP"
|
||||
)
|
||||
noextract=(
|
||||
"cheats.zip"
|
||||
"patches.zip"
|
||||
)
|
||||
|
||||
# Name of the .desktop file that will be installed.
|
||||
_desktopname=org.duckstation.DuckStation
|
||||
_destdir=/opt/duckstation
|
||||
|
||||
# https://wiki.archlinux.org/title/VCS_package_guidelines#Git
|
||||
# --dirty omitted, we need to ignore changes to this script because
|
||||
|
@ -70,6 +84,9 @@ pkgver() {
|
|||
prepare() {
|
||||
cd "${pkgname}"
|
||||
|
||||
# Copy resources
|
||||
cp "../cheats.zip" "../patches.zip" "data/resources"
|
||||
|
||||
# Are we creating a CI/official build?
|
||||
_tagpath="${startdir}/../../../src/scmversion/tag.h"
|
||||
if [[ -f "${_tagpath}" ]]; then
|
||||
|
@ -87,7 +104,7 @@ prepare() {
|
|||
./scripts/deps/build-dependencies-linux.sh \
|
||||
-system-freetype -system-harfbuzz -system-libjpeg \
|
||||
-system-libpng -system-libwebp -system-libzip \
|
||||
-system-zstd -system-qt \
|
||||
-system-zlib -system-zstd -system-qt \
|
||||
"${_depsdir}"
|
||||
fi
|
||||
}
|
||||
|
@ -108,7 +125,7 @@ build() {
|
|||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DALLOW_INSTALL=ON \
|
||||
-DINSTALL_SELF_CONTAINED=ON \
|
||||
-DCMAKE_INSTALL_PREFIX="${pkgdir}/opt/duckstation"
|
||||
-DCMAKE_INSTALL_PREFIX="${pkgdir}${_destdir}"
|
||||
ninja -C build-arch
|
||||
}
|
||||
|
||||
|
@ -116,8 +133,9 @@ package() {
|
|||
cd "${pkgname}"
|
||||
ninja -C build-arch install
|
||||
|
||||
# install wrapper script
|
||||
install -Dm755 scripts/packaging/duckstation-qt "${pkgdir}/usr/bin/duckstation-qt"
|
||||
# install alias
|
||||
mkdir -p "${pkgdir}/usr/bin"
|
||||
ln -s "${_destdir}/duckstation-qt" "${pkgdir}/usr/bin/duckstation-qt"
|
||||
|
||||
# install desktop file and icon
|
||||
install -Dm644 scripts/packaging/${_desktopname}.desktop "${pkgdir}/usr/share/applications/${_desktopname}.desktop"
|
||||
|
@ -127,4 +145,3 @@ package() {
|
|||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
install -Dm644 data/resources/thirdparty.html "${pkgdir}/usr/share/licenses/${pkgname}/thirdparty.html"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [[ -z "$I_WANT_A_BROKEN_WAYLAND_UI" ]]; then
|
||||
echo "Forcing X11 instead of Wayland, due to various protocol limitations"
|
||||
echo "and Qt issues. If you want to use Wayland, launch DuckStation with"
|
||||
echo "I_WANT_A_BROKEN_WAYLAND_UI=YES set."
|
||||
export QT_QPA_PLATFORM=xcb
|
||||
else
|
||||
echo "Wayland is not being disabled. Do not complain when things break."
|
||||
fi
|
||||
|
||||
exec /opt/duckstation/duckstation-qt "$@"
|
||||
|
|
@ -1,8 +1,13 @@
|
|||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
# NOTE: These package files are intended for your own personal/private use.
|
||||
# You do not have permission to upload them independently to other package repositories.
|
||||
#
|
||||
# To build:
|
||||
# git clone https://github.com/stenzek/duckstation.git
|
||||
# rpmbuild -bb scripts/packaging/fedora/duckstation.spec
|
||||
# sudo rpm -ivh ~/rpmbuild/RPMS/duckstation-*.rpm
|
||||
|
||||
Name: duckstation
|
||||
Version: 0.0.0
|
||||
|
@ -14,7 +19,7 @@ BuildRequires: alsa-lib-devel, clang, cmake, dbus-devel, egl-wayland-devel, extr
|
|||
BuildRequires: extra-cmake-modules, freetype-devel, libavcodec-free-devel, libavformat-free-devel
|
||||
BuildRequires: libavutil-free-devel, libcurl-devel, libevdev-devel, libswresample-free-devel
|
||||
BuildRequires: libswscale-free-devel, libpng-devel, libwebp-devel, libX11-devel, libXrandr-devel
|
||||
BuildRequires: libzip-devel, libzstd-devel, lld, llvm, make, mesa-libEGL-devel, mesa-libGL-devel
|
||||
BuildRequires: libzip-devel, libzip-tools, libzstd-devel, lld, llvm, make, mesa-libEGL-devel, mesa-libGL-devel
|
||||
BuildRequires: ninja-build, patch, pipewire-devel pulseaudio-libs-devel, wayland-devel, zlib-devel
|
||||
BuildRequires: qt6-qtbase-devel, qt6-qtbase-private-devel, qt6-qttools, qt6-qttools-devel
|
||||
|
||||
|
@ -28,7 +33,7 @@ Requires: qt6-qtbase qt6-qtbase-gui qt6-qtimageformats qt6-qtsvg
|
|||
%undefine _include_frame_pointers
|
||||
|
||||
# Defines -O2, -flto, and others. We manage LTO ourselves.
|
||||
%global _general_options "-O2" "-pipe"
|
||||
%global _general_options "-O3" "-pipe"
|
||||
%global _preprocessor_defines ""
|
||||
|
||||
# We include debug information in the main package for user backtrace reporting.
|
||||
|
@ -44,6 +49,8 @@ DuckStation is an simulator/emulator of the Sony PlayStation(TM) console, focusi
|
|||
%prep
|
||||
%setup -n duckstation -c -T
|
||||
git clone file://%{SOURCEURL0} .
|
||||
curl -L -o "data/resources/cheats.zip" "https://github.com/duckstation/chtdb/releases/download/latest/cheats.zip"
|
||||
curl -L -o "data/resources/patches.zip" "https://github.com/duckstation/chtdb/releases/download/latest/patches.zip"
|
||||
if [ -f "%{SOURCEURL0}/src/scmversion/tag.h" ]; then
|
||||
echo "Copying SCM release tag..."
|
||||
cp "%{SOURCEURL0}/src/scmversion/tag.h" src/scmversion
|
||||
|
@ -52,7 +59,7 @@ fi
|
|||
%build
|
||||
|
||||
if [ ! -d "${PWD}/deps" ]; then
|
||||
scripts/deps/build-dependencies-linux.sh -system-freetype -system-harfbuzz -system-libjpeg -system-libpng -system-libwebp -system-libzip -system-zstd -system-qt "${PWD}/deps"
|
||||
scripts/deps/build-dependencies-linux.sh -system-freetype -system-harfbuzz -system-libjpeg -system-libpng -system-libwebp -system-libzip -system-zlib -system-zstd -system-qt "${PWD}/deps"
|
||||
fi
|
||||
|
||||
rm -fr build
|
||||
|
@ -70,7 +77,8 @@ ninja -C build %{?_smp_mflags}
|
|||
%install
|
||||
rm -fr %{buildroot}
|
||||
ninja -C build install
|
||||
install -Dm755 scripts/packaging/duckstation-qt %{buildroot}/usr/bin/duckstation-qt
|
||||
mkdir -p %{buildroot}/usr/bin
|
||||
ln -s /opt/duckstation/duckstation-qt %{buildroot}/usr/bin/duckstation-qt
|
||||
install -Dm644 scripts/packaging/org.duckstation.DuckStation.png %{buildroot}/usr/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png
|
||||
install -Dm644 scripts/packaging/org.duckstation.DuckStation.desktop %{buildroot}/usr/share/applications/org.duckstation.DuckStation.desktop
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
name: libzip
|
||||
|
@ -26,7 +26,7 @@ build-options:
|
|||
sources:
|
||||
- type: git
|
||||
url: "https://github.com/nih-at/libzip.git"
|
||||
commit: "64b62d6b1a686a1b0bac1b6b9dcb635be0499afb"
|
||||
commit: "f30f5290de485348442d168cd7b2eb714d1f20f9"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
||||
|
|
|
@ -14,7 +14,7 @@ build-options:
|
|||
sources:
|
||||
- type: git
|
||||
url: "https://github.com/stenzek/shaderc.git"
|
||||
commit: "1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6"
|
||||
commit: "fc65b19d2098cf81e55b4edc10adad2ad8268361"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
|
@ -22,8 +22,8 @@ build-options:
|
|||
sources:
|
||||
- type: git
|
||||
url: "https://github.com/KhronosGroup/SPIRV-Cross.git"
|
||||
tag: "vulkan-sdk-1.3.290.0"
|
||||
commit: "5d127b917f080c6f052553c47170ec0ba702e54f"
|
||||
tag: "vulkan-sdk-1.4.304.0"
|
||||
commit: "ebe2aa0cd80f5eb5cd8a605da604cacf72205f3b"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
name: cpuinfo
|
||||
|
@ -20,7 +20,7 @@ build-options:
|
|||
sources:
|
||||
- type: git
|
||||
url: "https://github.com/stenzek/cpuinfo.git"
|
||||
commit: "7524ad504fdcfcf75a18a133da6abd75c5d48053"
|
||||
commit: "3ebbfd45645650c4940bf0f3b4d25ab913466bb0"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
name: soundtouch
|
||||
|
@ -9,8 +9,8 @@ config-opts:
|
|||
|
||||
# Use clang with LTO for speed.
|
||||
- "-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/llvm19/bin/clang"
|
||||
- "-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm19/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"
|
|
@ -1,7 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
name: sdl2
|
||||
name: sdl3
|
||||
buildsystem: cmake-ninja
|
||||
builddir: true
|
||||
config-opts:
|
||||
|
@ -11,11 +11,12 @@ config-opts:
|
|||
- "-DSDL_STATIC=OFF"
|
||||
- "-DSDL_TESTS=OFF"
|
||||
build-options:
|
||||
strip: true
|
||||
strip: false
|
||||
no-debuginfo: true
|
||||
sources:
|
||||
- type: archive
|
||||
url: "https://github.com/libsdl-org/SDL/releases/download/release-2.30.11/SDL2-2.30.11.tar.gz"
|
||||
sha256: "8b8d4aef2038533da814965220f88f77d60dfa0f32685f80ead65e501337da7f"
|
||||
url: "https://github.com/libsdl-org/SDL/releases/download/release-3.2.8/SDL3-3.2.8.tar.gz"
|
||||
sha256: "13388fabb361de768ecdf2b65e52bb27d1054cae6ccb6942ba926e378e00db03"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
app-id: "org.duckstation.DuckStation"
|
||||
|
@ -6,7 +6,7 @@ runtime: "org.kde.Platform"
|
|||
runtime-version: "6.8"
|
||||
sdk: "org.kde.Sdk"
|
||||
sdk-extensions:
|
||||
- "org.freedesktop.Sdk.Extension.llvm18"
|
||||
- "org.freedesktop.Sdk.Extension.llvm19"
|
||||
add-extensions:
|
||||
"org.freedesktop.Platform.ffmpeg-full":
|
||||
directory: "lib/ffmpeg"
|
||||
|
@ -23,22 +23,20 @@ finish-args:
|
|||
- "--share=ipc"
|
||||
- "--socket=pulseaudio"
|
||||
- "--talk-name=org.freedesktop.ScreenSaver"
|
||||
|
||||
# Wayland is disabled due to various QtWayland issues, causing broken UI.
|
||||
- "--socket=x11"
|
||||
- "--env=QT_QPA_PLATFORM=xcb"
|
||||
- "--socket=wayland"
|
||||
- "--socket=fallback-x11"
|
||||
|
||||
modules:
|
||||
# Dependencies.
|
||||
- "modules/10-libbacktrace.yaml"
|
||||
- "modules/11-libzip.yaml"
|
||||
- "modules/20-sdl2.yaml"
|
||||
- "modules/21-shaderc.yaml"
|
||||
- "modules/22-spirv-cross.yaml"
|
||||
- "modules/23-cpuinfo.yaml"
|
||||
- "modules/24-discord-rpc.yaml"
|
||||
- "modules/25-soundtouch.yaml"
|
||||
- "modules/26-lunasvg.yaml"
|
||||
- "modules/20-shaderc.yaml"
|
||||
- "modules/21-spirv-cross.yaml"
|
||||
- "modules/22-cpuinfo.yaml"
|
||||
- "modules/23-discord-rpc.yaml"
|
||||
- "modules/24-soundtouch.yaml"
|
||||
- "modules/25-lunasvg.yaml"
|
||||
- "modules/30-sdl3.yaml"
|
||||
|
||||
# Main module.
|
||||
- name: duckstation
|
||||
|
@ -73,8 +71,8 @@ modules:
|
|||
|
||||
# Make sure we're using ThinLTO.
|
||||
- "-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/llvm19/bin/clang"
|
||||
- "-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm19/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"
|
||||
|
|
|
@ -10,6 +10,44 @@
|
|||
<description>
|
||||
<p>DuckStation is an simulator/emulator of the Sony PlayStation(TM) console, focusing on playability, speed, and long-term maintainability. The goal is to be as accurate as possible while maintaining performance suitable for low-end devices.</p>
|
||||
<p>"Hack" options are discouraged, the default configuration should support all playable games with only some of the enhancements having compatibility issues.</p>
|
||||
<p>DuckStation features a fully-featured frontend built using Qt, as well as a fullscreen/TV UI based on Dear ImGui. Other features include:</p>
|
||||
<ul>
|
||||
<li>Hardware renderer supporting OpenGL and Vulkan APIs.</li>
|
||||
<li>Upscaling, texture filtering, and true colour (24-bit) in hardware renderers.</li>
|
||||
<li>PGXP for geometry precision, texture correction, and depth buffer emulation.</li>
|
||||
<li>Accurate blending via Rasterizer Order Views/Fragment Shader Interlock.</li>
|
||||
<li>Texture replacement system in hardware renderers.</li>
|
||||
<li>Vectorized and multi-threaded software renderer.</li>
|
||||
<li>Motion adaptive deinterlacing.</li>
|
||||
<li>Adaptive downsampling filter.</li>
|
||||
<li>Screen rotation for vertical or "TATE" shmup games.</li>
|
||||
<li>Post processing shader chains (GLSL and Reshade FX).</li>
|
||||
<li>Border overlays/bezels displayed around game content.</li>
|
||||
<li>"Fast boot" for skipping BIOS splash/intro.</li>
|
||||
<li>Save state support, with runahead and rewind.</li>
|
||||
<li>Supports reading directly from CD, bin/cue images, raw bin/img files, MAME CHD, single-track ECM, MDS/MDF, and unencrypted PBP formats.</li>
|
||||
<li>Preloading of disc images to RAM to avoid disk sleeping hitches.</li>
|
||||
<li>Merging of multi-disc games in game list/grid with memory cards shared between discs.</li>
|
||||
<li>Automatic loading/applying of PPF patches.</li>
|
||||
<li>Direct booting of homebrew executables.</li>
|
||||
<li>Direct loading of Portable Sound Format (psf) files.</li>
|
||||
<li>Time stretched audio when running outside of 100% speed.</li>
|
||||
<li>Digital and analog controllers for input (rumble is forwarded to host).</li>
|
||||
<li>GunCon and Justifier lightgun support (simulated with mouse).</li>
|
||||
<li>NeGcon support.</li>
|
||||
<li>Controller presets and per-game configuration.</li>
|
||||
<li>Automatic content scanning - game titles/hashes are provided by redump.org.</li>
|
||||
<li>Optional automatic switching of memory cards for each game.</li>
|
||||
<li>Supports loading cheats from existing lists.</li>
|
||||
<li>Memory card editor and save importer.</li>
|
||||
<li>Emulated CPU overclocking.</li>
|
||||
<li>Integrated and remote debugging.</li>
|
||||
<li>Multitap controllers (up to 8 devices).</li>
|
||||
<li>RetroAchievements.</li>
|
||||
<li>Video capture with FFmpeg backends.</li>
|
||||
<li>Free camera function.</li>
|
||||
<li>Parallel port cartridge emulation.</li>
|
||||
</ul>
|
||||
<p>"PlayStation" and "PSX" are registered trademarks of Sony Interactive Entertainment Europe Limited. This project is not affiliated in any way with Sony Interactive Entertainment.</p>
|
||||
</description>
|
||||
<content_rating type="oars-1.1"/>
|
||||
|
@ -19,13 +57,21 @@
|
|||
<url type="vcs-browser">https://github.com/stenzek/duckstation</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/stenzek/duckstation/md-images/main-qt.png</image>
|
||||
<image>https://raw.githubusercontent.com/stenzek/duckstation/md-images/linux-main-qt.png</image>
|
||||
<caption>Desktop Interface</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/stenzek/duckstation/md-images/bigduck.png</image>
|
||||
<image>https://raw.githubusercontent.com/stenzek/duckstation/md-images/linux-bigpicture.png</image>
|
||||
<caption>Big Picture Mode Interface</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/stenzek/duckstation/md-images/linux-hover.png</image>
|
||||
<caption>Hover Racing Game</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/stenzek/duckstation/md-images/linux-fromage.png</image>
|
||||
<caption>Fromage Game</caption>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="@GIT_VERSION@" date="@GIT_DATE@" />
|
||||
|
|