mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-05 22:04:33 +00:00
Compare commits
406 Commits
wip4
...
downsampli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
113614c2f5 | ||
|
|
ac41ace972 | ||
|
|
ebe782e4f4 | ||
|
|
e7439c1503 | ||
|
|
fda87de7e7 | ||
|
|
116bc83d09 | ||
|
|
ddffc055b9 | ||
|
|
1063c3da7f | ||
|
|
0a124ee839 | ||
|
|
2b7b3d8729 | ||
|
|
dacbb7c718 | ||
|
|
6318223f58 | ||
|
|
092e819a07 | ||
|
|
cae1ddc971 | ||
|
|
dc9cdddd4c | ||
|
|
0960160589 | ||
|
|
1765590a6f | ||
|
|
9f41ef9eac | ||
|
|
5ee069fc63 | ||
|
|
4d6124d41b | ||
|
|
a5d90c0b22 | ||
|
|
6043b2331f | ||
|
|
886040b257 | ||
|
|
8353a33e89 | ||
|
|
076f4a6293 | ||
|
|
920f25427e | ||
|
|
78ccbc710c | ||
|
|
548f1da5af | ||
|
|
9054801341 | ||
|
|
80855090d5 | ||
|
|
db14824d61 | ||
|
|
547601559c | ||
|
|
52e6e8ff1e | ||
|
|
f9bb413a40 | ||
|
|
dda10d3576 | ||
|
|
b2c8d25638 | ||
|
|
88cd086633 | ||
|
|
e096827df8 | ||
|
|
e08dda0a0a | ||
|
|
87e367076d | ||
|
|
ba15a76d7b | ||
|
|
d3fe1dfc2c | ||
|
|
fc5553a8c7 | ||
|
|
90cb266886 | ||
|
|
83b4757788 | ||
|
|
08cd649187 | ||
|
|
cd873eb6c1 | ||
|
|
3a64c5e4b3 | ||
|
|
b21312867b | ||
|
|
179e2f1999 | ||
|
|
0fdf984b71 | ||
|
|
e036318559 | ||
|
|
c11468b9f1 | ||
|
|
37e5e64ddc | ||
|
|
f3b7686457 | ||
|
|
5ac5a1d246 | ||
|
|
1d63648d68 | ||
|
|
dcd439e7d8 | ||
|
|
22202f1607 | ||
|
|
d0e1efb1fd | ||
|
|
f51dda3e66 | ||
|
|
a08acdb93a | ||
|
|
8605722cdf | ||
|
|
57be62ffd1 | ||
|
|
884459d1cf | ||
|
|
ffef0c2e38 | ||
|
|
d69d25431e | ||
|
|
f25302c847 | ||
|
|
34f2600f99 | ||
|
|
4c08c716c4 | ||
|
|
a4b359672c | ||
|
|
79b0533df2 | ||
|
|
b76618fdf4 | ||
|
|
1bf076c74f | ||
|
|
e0877c1922 | ||
|
|
69826f2101 | ||
|
|
a3645f3173 | ||
|
|
7228f6f1cf | ||
|
|
3c5db39ee4 | ||
|
|
4d4523dc04 | ||
|
|
c5bd4101b3 | ||
|
|
9cd9042563 | ||
|
|
4e928d7ce1 | ||
|
|
d65ae6ce00 | ||
|
|
401582bb2b | ||
|
|
a08bd43000 | ||
|
|
156b3f989b | ||
|
|
9cba1decad | ||
|
|
468c907fd6 | ||
|
|
d4e393f1a8 | ||
|
|
ab107722f7 | ||
|
|
242561debf | ||
|
|
82a843c121 | ||
|
|
1ed9e609a5 | ||
|
|
b7832e609f | ||
|
|
1a211e0a21 | ||
|
|
0e6ade067c | ||
|
|
5c3abb490d | ||
|
|
799f5bdf97 | ||
|
|
8c807118c0 | ||
|
|
7bb0c7d1fb | ||
|
|
c2589461e9 | ||
|
|
74fd217afb | ||
|
|
25b0bb752a | ||
|
|
c99625e4c3 | ||
|
|
58b0ccf3fc | ||
|
|
69ed6e5e58 | ||
|
|
2da692b341 | ||
|
|
2a8cfc7922 | ||
|
|
4e5b4ba071 | ||
|
|
4b34825afd | ||
|
|
ce71b168c3 | ||
|
|
a44dd1882f | ||
|
|
7b9664d6f2 | ||
|
|
9921d2074c | ||
|
|
5c83bbe5c5 | ||
|
|
272aa4f933 | ||
|
|
55c5e17fdc | ||
|
|
750dd1cb87 | ||
|
|
fa993849f7 | ||
|
|
6903abba55 | ||
|
|
0528ce567c | ||
|
|
00eb54cd15 | ||
|
|
d360564cef | ||
|
|
8c2fe430d8 | ||
|
|
b03127b206 | ||
|
|
6f3e9913f5 | ||
|
|
dd180f2fd6 | ||
|
|
b33aa31db8 | ||
|
|
8f6db2c8fa | ||
|
|
b81c87958f | ||
|
|
d010f768c4 | ||
|
|
ad7318f5f9 | ||
|
|
e7ff547f1b | ||
|
|
0565320036 | ||
|
|
c4e0e7fade | ||
|
|
dc18ce2c2a | ||
|
|
f4265edb2d | ||
|
|
86d78e5eca | ||
|
|
33083cfae1 | ||
|
|
00278fa905 | ||
|
|
b8fa97e1a7 | ||
|
|
89f11095bc | ||
|
|
9f73e690ad | ||
|
|
ac05c35292 | ||
|
|
18c509a679 | ||
|
|
307bd86b72 | ||
|
|
2aa466d1c6 | ||
|
|
9a22ac3c70 | ||
|
|
8e254c4baf | ||
|
|
f3f99f7eac | ||
|
|
406cd1b6a1 | ||
|
|
9e04b0bf55 | ||
|
|
a8361f985e | ||
|
|
7f1ebd3767 | ||
|
|
448009f4ef | ||
|
|
515a4d07fb | ||
|
|
0b4e302c22 | ||
|
|
b81287efd2 | ||
|
|
9b62632951 | ||
|
|
556a53e564 | ||
|
|
a919fa71aa | ||
|
|
080d30bf0c | ||
|
|
ad980a7004 | ||
|
|
0aa89ec7b0 | ||
|
|
9b97bd5924 | ||
|
|
e1bd5690ac | ||
|
|
01dfc9ae51 | ||
|
|
62285dcf33 | ||
|
|
6b754e6759 | ||
|
|
26db661a05 | ||
|
|
c4b0430d5e | ||
|
|
7826c258b0 | ||
|
|
2d659fc3eb | ||
|
|
831c982f3b | ||
|
|
6993e6c31f | ||
|
|
10e2079ee4 | ||
|
|
fe1fa765f7 | ||
|
|
568667753d | ||
|
|
7116a80435 | ||
|
|
31c1cfa650 | ||
|
|
2f5bdc9651 | ||
|
|
7442ec2f19 | ||
|
|
fa2442deaf | ||
|
|
8df2a2c446 | ||
|
|
f010d81652 | ||
|
|
b68370dff7 | ||
|
|
cc52320dfe | ||
|
|
4216eef420 | ||
|
|
585b13fbd9 | ||
|
|
b634eecd21 | ||
|
|
23c221be01 | ||
|
|
edfeffd820 | ||
|
|
fda10a6978 | ||
|
|
43af57d735 | ||
|
|
1f1a664908 | ||
|
|
6e2223b517 | ||
|
|
fbb411a946 | ||
|
|
4e1e07a93c | ||
|
|
9d52e27e16 | ||
|
|
666fee2df7 | ||
|
|
2603ce5976 | ||
|
|
03e24637af | ||
|
|
d00627b44b | ||
|
|
5e21234966 | ||
|
|
90e9634c19 | ||
|
|
c0c2e69b59 | ||
|
|
5cbb6b6163 | ||
|
|
e91ae5f1b9 | ||
|
|
dcaee9b87e | ||
|
|
726aa67d1b | ||
|
|
b99fb22522 | ||
|
|
b832dfbb3a | ||
|
|
c25c0067af | ||
|
|
e683c89770 | ||
|
|
5687dd22bd | ||
|
|
2f6eaa1d43 | ||
|
|
0dbab167a8 | ||
|
|
ceef778891 | ||
|
|
25ffc5a248 | ||
|
|
50fbaf90e6 | ||
|
|
8f19912c64 | ||
|
|
db848d1381 | ||
|
|
5577328f35 | ||
|
|
99f133223c | ||
|
|
2e805d56dd | ||
|
|
c3a2156c79 | ||
|
|
cdcf05a878 | ||
|
|
e507fdcb1f | ||
|
|
d8af8e4a60 | ||
|
|
9743ce01a0 | ||
|
|
69947fb907 | ||
|
|
d871c17f3f | ||
|
|
5eac1e4800 | ||
|
|
1edcc8c0ac | ||
|
|
cc567d9498 | ||
|
|
e137d3b5c7 | ||
|
|
5767397231 | ||
|
|
0bb83f6fd7 | ||
|
|
1e839224e8 | ||
|
|
2e6deca76f | ||
|
|
b814666134 | ||
|
|
1bea8817f1 | ||
|
|
42535591bc | ||
|
|
a1928de4d0 | ||
|
|
8bb013540d | ||
|
|
09ba2ed181 | ||
|
|
765a46fc88 | ||
|
|
53c08c52ed | ||
|
|
5d7cb6c5dc | ||
|
|
a4af88bc52 | ||
|
|
31d953dac2 | ||
|
|
9b0a906297 | ||
|
|
5bf7227790 | ||
|
|
1adf36ccb2 | ||
|
|
b6eb41e2cf | ||
|
|
2999f15d7a | ||
|
|
7f3687de81 | ||
|
|
3a661a1c3d | ||
|
|
d5432da082 | ||
|
|
f9155e5ce7 | ||
|
|
5725a0360b | ||
|
|
8c5fadafba | ||
|
|
dbba8deb4b | ||
|
|
c3a9ab3cc8 | ||
|
|
f0c456893c | ||
|
|
acf04ed67a | ||
|
|
e22d67f4aa | ||
|
|
9c327af280 | ||
|
|
52feb1a37d | ||
|
|
c9c4307871 | ||
|
|
042a2d72f7 | ||
|
|
5c4d95fd51 | ||
|
|
6d080c1a3f | ||
|
|
3670c131e3 | ||
|
|
ea632665c1 | ||
|
|
0c7636b3c3 | ||
|
|
541985fb70 | ||
|
|
58f5d7e1ba | ||
|
|
e9644c7eeb | ||
|
|
20df4ec14e | ||
|
|
fe3b4154b7 | ||
|
|
3ca2579882 | ||
|
|
84a1e209ea | ||
|
|
04e472d088 | ||
|
|
d93c713fb7 | ||
|
|
5b6e3a952c | ||
|
|
0a2facfaeb | ||
|
|
d3ceda0c5b | ||
|
|
9a5ee3aae6 | ||
|
|
03eb4a6bf9 | ||
|
|
25063d4018 | ||
|
|
14ff89d0c0 | ||
|
|
297165d1ee | ||
|
|
cbc22a89f7 | ||
|
|
ac79e43cc0 | ||
|
|
3959c83bd4 | ||
|
|
22edf23269 | ||
|
|
6756c96fa2 | ||
|
|
71e1032605 | ||
|
|
2f70d1bd9c | ||
|
|
e9848a6182 | ||
|
|
9df59713da | ||
|
|
0faa9cf650 | ||
|
|
2a7625e67c | ||
|
|
4aa9857c53 | ||
|
|
aff623b772 | ||
|
|
7c627a8c83 | ||
|
|
f9c125c1a1 | ||
|
|
d7d028ac5c | ||
|
|
b87c6dde6c | ||
|
|
4fe3e1147d | ||
|
|
9fc9f4b9e9 | ||
|
|
00132c6070 | ||
|
|
9c2244f40e | ||
|
|
42c5f9169f | ||
|
|
c6746e76f1 | ||
|
|
62414b0c4c | ||
|
|
67041d217b | ||
|
|
145ad2db27 | ||
|
|
9dec34c8c0 | ||
|
|
f1435dcf67 | ||
|
|
53008eb34a | ||
|
|
c6e2235ee2 | ||
|
|
fa4dc381ed | ||
|
|
dfacf9e8db | ||
|
|
ee750b44e3 | ||
|
|
0f51472d64 | ||
|
|
b7fff840c8 | ||
|
|
cbc16bee9e | ||
|
|
b059cda8d5 | ||
|
|
aafc029682 | ||
|
|
ae18db9271 | ||
|
|
682ba71319 | ||
|
|
d5b9b54a69 | ||
|
|
19eee76aec | ||
|
|
6cbfab6eca | ||
|
|
9970944da2 | ||
|
|
5401dc8d52 | ||
|
|
ff3214b8f7 | ||
|
|
d3246deb77 | ||
|
|
83274c7e3b | ||
|
|
b39f1558ec | ||
|
|
c0b4627c11 | ||
|
|
bbe6612b25 | ||
|
|
da501b9294 | ||
|
|
2e31a40dda | ||
|
|
dac5dd562b | ||
|
|
6d72a48708 | ||
|
|
3ed6cc2ba8 | ||
|
|
6be242449b | ||
|
|
eeee1e691a | ||
|
|
208e6c4b35 | ||
|
|
c4d4a7a774 | ||
|
|
73dc52ac98 | ||
|
|
cd216d91db | ||
|
|
2e0825a363 | ||
|
|
b81d6718f4 | ||
|
|
4e43b1ec8c | ||
|
|
a879c11c34 | ||
|
|
97700b85de | ||
|
|
eb390a9b5d | ||
|
|
b28ca2b78a | ||
|
|
57d3aa4850 | ||
|
|
1434507b41 | ||
|
|
b97788a35a | ||
|
|
4edae3cdd0 | ||
|
|
d1b904a1da | ||
|
|
0befbf8021 | ||
|
|
be7a20fef2 | ||
|
|
5fd79254bd | ||
|
|
57595c47af | ||
|
|
4a650fcce2 | ||
|
|
982dccb990 | ||
|
|
b180b26728 | ||
|
|
dec468966c | ||
|
|
a804801a1b | ||
|
|
0ae8fcced3 | ||
|
|
0076af6974 | ||
|
|
40a1bee9ea | ||
|
|
9fa8fee193 | ||
|
|
852239ec8a | ||
|
|
70a4b5c9f2 | ||
|
|
7b230dc4c1 | ||
|
|
ae14c8715d | ||
|
|
8567293103 | ||
|
|
7eb1d4e092 | ||
|
|
24dfd30839 | ||
|
|
3ff1b04576 | ||
|
|
e647192437 | ||
|
|
affbdfc350 | ||
|
|
ff010686f8 | ||
|
|
c970740d12 | ||
|
|
e987b56aae | ||
|
|
88836c431e | ||
|
|
5bcf99fc11 | ||
|
|
5261cfe8e4 | ||
|
|
f67eacc071 | ||
|
|
d2d06adeeb | ||
|
|
5c03e1d940 | ||
|
|
bb24d406f2 | ||
|
|
d26fc89aac | ||
|
|
5d8519897d | ||
|
|
b984f343ae | ||
|
|
0079f7a285 | ||
|
|
e6892e0a54 |
9
.github/workflows/linux-appimage-build.yml
vendored
9
.github/workflows/linux-appimage-build.yml
vendored
@@ -2,6 +2,7 @@ name: 🐧 Linux AppImage
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux-x64-appimage-build:
|
||||
@@ -14,7 +15,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Packages
|
||||
run: scripts/appimage/install-packages.sh
|
||||
run: scripts/packaging/appimage/install-packages.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
@@ -66,7 +67,7 @@ jobs:
|
||||
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 --build . --parallel
|
||||
cd ..
|
||||
scripts/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
@@ -85,7 +86,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Packages
|
||||
run: scripts/appimage/install-packages.sh
|
||||
run: scripts/packaging/appimage/install-packages.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
@@ -137,7 +138,7 @@ jobs:
|
||||
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 --build . --parallel
|
||||
cd ..
|
||||
scripts/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64-SSE2
|
||||
scripts/packaging/appimage/make-appimage.sh $(realpath .) $(realpath ./build) $HOME/deps DuckStation-x64-SSE2
|
||||
|
||||
- name: Upload Qt AppImage
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
|
||||
13
.github/workflows/linux-flatpak-build.yml
vendored
13
.github/workflows/linux-flatpak-build.yml
vendored
@@ -11,6 +11,7 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: "stable"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux-flatpak-build:
|
||||
@@ -59,21 +60,21 @@ jobs:
|
||||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
scripts/generate-metainfo.sh scripts/flatpak
|
||||
cat scripts/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
scripts/packaging/generate-metainfo.sh scripts/packaging/flatpak
|
||||
cat scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate AppStream XML
|
||||
run: flatpak-builder-lint appstream scripts/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
run: flatpak-builder-lint appstream scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml
|
||||
|
||||
- name: Validate Manifest
|
||||
run: flatpak-builder-lint manifest scripts/flatpak/org.duckstation.DuckStation.yaml
|
||||
run: flatpak-builder-lint manifest scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
with:
|
||||
bundle: duckstation-x64.flatpak
|
||||
upload-artifact: false
|
||||
manifest-path: scripts/flatpak/org.duckstation.DuckStation.yaml
|
||||
manifest-path: scripts/packaging/flatpak/org.duckstation.DuckStation.yaml
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
@@ -81,7 +82,7 @@ jobs:
|
||||
branch: stable
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/flatpak/**/*.yaml') }}
|
||||
cache-key: flatpak-x64-${{ hashFiles('scripts/packaging/flatpak/**/*.yaml') }}
|
||||
|
||||
- name: Validate Build
|
||||
run: |
|
||||
|
||||
5
.github/workflows/macos-build.yml
vendored
5
.github/workflows/macos-build.yml
vendored
@@ -2,6 +2,7 @@ name: 🍎 MacOS
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
macos-build:
|
||||
@@ -13,8 +14,8 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Xcode 15.4
|
||||
run: sudo xcode-select -s /Applications/Xcode_15.4.app
|
||||
- name: Use Xcode 16.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_16.1.app
|
||||
|
||||
- name: Install packages
|
||||
shell: bash
|
||||
|
||||
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: Automated Builds
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
1
.github/workflows/windows-build.yml
vendored
1
.github/workflows/windows-build.yml
vendored
@@ -2,6 +2,7 @@ name: 💻 Windows
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
windows-x64-build:
|
||||
|
||||
@@ -42,10 +42,6 @@ if(LINUX OR BSD)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
# Set _DEBUG macro for Debug builds.
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
|
||||
# Release build optimizations for MSVC.
|
||||
if(MSVC)
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS")
|
||||
@@ -59,14 +55,18 @@ if(MSVC)
|
||||
|
||||
# RelWithDebInfo is set to Ob1 instead of Ob2.
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_C_FLAGS_DEVEL "${CMAKE_C_FLAGS_DEVEL}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Ob1" "/Ob2" CMAKE_CXX_FLAGS_DEVEL "${CMAKE_CXX_FLAGS_DEVEL}")
|
||||
|
||||
# Disable incremental linking in RelWithDebInfo.
|
||||
string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_DEVEL}")
|
||||
|
||||
# COMDAT folding/remove unused functions.
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_DEVEL} /OPT:REF /OPT:ICF")
|
||||
endif()
|
||||
|
||||
# Warning disables.
|
||||
|
||||
@@ -16,3 +16,17 @@ endif()
|
||||
if(APPLE)
|
||||
option(SKIP_POSTPROCESS_BUNDLE "Disable bundle post-processing, including Qt additions" OFF)
|
||||
endif()
|
||||
|
||||
# Set _DEBUG macro for Debug builds.
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
|
||||
# Create the Devel build type based on RelWithDebInfo.
|
||||
set(CMAKE_C_FLAGS_DEVEL "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEVEL" CACHE STRING "Flags used by the C compiler during DEVEL builds." FORCE)
|
||||
set(CMAKE_CXX_FLAGS_DEVEL "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_DEVEL" CACHE STRING "Flags used by the CXX compiler during DEVEL builds." FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used for the linker during DEVEL builds." FORCE)
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEVEL "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of modules during DEVEL builds." FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of shared libraries during DEVEL builds." FORCE)
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_DEVEL "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the linker during the creation of static libraries during DEVEL builds." FORCE)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES "Devel")
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL CMAKE_MODULE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_STATIC_LINKER_FLAGS_DEVEL)
|
||||
|
||||
@@ -92,17 +92,22 @@ function(detect_architecture)
|
||||
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "riscv64")
|
||||
message(STATUS "Building RISC-V 64 binaries.")
|
||||
set(CPU_ARCH_RISCV64 TRUE PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finline-atomics" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -finline-atomics" PARENT_SCOPE)
|
||||
|
||||
# Still need this, apparently.
|
||||
link_libraries("-latomic")
|
||||
# Don't want function calls for atomics.
|
||||
if(COMPILER_GCC)
|
||||
set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -finline-atomics")
|
||||
|
||||
# Still need this, apparently.
|
||||
link_libraries("-latomic")
|
||||
endif()
|
||||
|
||||
if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
# Frame pointers generate an annoying amount of code on leaf functions.
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer" PARENT_SCOPE)
|
||||
set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fomit-frame-pointer")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}" PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown system processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
@@ -121,8 +126,8 @@ function(detect_page_size)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(HOST_MIN_PAGE_SIZE OR HOST_MAX_PAGE_SIZE)
|
||||
if(NOT HOST_MIN_PAGE_SIZE OR NOT HOST_MAX_PAGE_SIZE)
|
||||
if(DEFINED HOST_MIN_PAGE_SIZE OR DEFINED HOST_MAX_PAGE_SIZE)
|
||||
if(NOT DEFINED HOST_MIN_PAGE_SIZE OR NOT DEFINED HOST_MAX_PAGE_SIZE)
|
||||
message(FATAL_ERROR "Both HOST_MIN_PAGE_SIZE and HOST_MAX_PAGE_SIZE must be defined.")
|
||||
endif()
|
||||
return()
|
||||
@@ -172,7 +177,7 @@ function(detect_cache_line_size)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
message(WARNING "Cross-compiling and can't determine page size, assuming default.")
|
||||
message(WARNING "Cross-compiling and can't determine cache line size, assuming default.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 241 B After Width: | Height: | Size: 241 B |
2
data/resources/images/flags/Russian.svg
Normal file
2
data/resources/images/flags/Russian.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 6" width="900" height="600"><rect fill="#fff" width="9" height="3"/><rect fill="#d52b1e" y="3" width="9" height="3"/><rect fill="#0039a6" y="2" width="9" height="2"/></svg>
|
||||
|
After Width: | Height: | Size: 266 B |
5
data/resources/images/flags/Turkish.svg
Normal file
5
data/resources/images/flags/Turkish.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 -30000 90000 60000">
|
||||
<title>Flag of Turkey</title>
|
||||
<path fill="#e30a17" d="m0-30000h90000v60000H0z"/>
|
||||
<path fill="#fff" d="m41750 0 13568-4408-8386 11541V-7133l8386 11541zm925 8021a15000 15000 0 1 1 0-16042 12000 12000 0 1 0 0 16042z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 323 B |
@@ -4,7 +4,7 @@ Czech.svg: https://commons.wikimedia.org/wiki/Flag_of_the_Czech_Republic.svg
|
||||
Danish.svg: https://commons.wikimedia.org/wiki/Flag_of_Denmark.svg
|
||||
Dutch.svg: https://commons.wikimedia.org/wiki/Flag_of_the_Netherlands.svg
|
||||
English.svg: https://commons.wikimedia.org/wiki/Flag_of_the_United_Kingdom_(1-2).svg
|
||||
Finish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Finland.svg
|
||||
Finnish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Finland.svg
|
||||
French.svg: https://commons.wikimedia.org/wiki/File:Flag_of_France.svg
|
||||
German.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Germany.svg
|
||||
Greek.svg: https://commons.wikimedia.org/wiki/Flag_of_Greece.svg
|
||||
@@ -17,4 +17,5 @@ Polish.svg: https://commons.wikimedia.org/wiki/Flag_of_Poland.svg
|
||||
Portuguese.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Portugal.svg
|
||||
Spanish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Spain.svg
|
||||
Swedish.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Sweden.svg
|
||||
Russian.svg: https://commons.wikimedia.org/wiki/File:Flag_of_Russia.svg
|
||||
Other.svg: https://en.wikipedia.org/wiki/File:Flag_with_question_mark.svg
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
// EPX.glc
|
||||
// Copyright 2020 Morgan McGuire & Mara Gagiu,
|
||||
// provided under the Open Source MIT license https://opensource.org/licenses/MIT
|
||||
|
||||
// Implementation of Eric Johnston and Andrea Mazzoleni's
|
||||
// EPX aka Scale2X algorithm based on https://www.scale2x.it/algorithm
|
||||
|
||||
#define ABGR8 uint
|
||||
|
||||
UNIFORM_BLOCK_LAYOUT uniform UBOBlock {
|
||||
ivec2 src_size;
|
||||
ivec2 dst_size;
|
||||
};
|
||||
|
||||
TEXTURE_LAYOUT(0) uniform sampler2D samp0;
|
||||
IMAGE_LAYOUT(0, rgba8) uniform restrict writeonly image2D dst_image;
|
||||
|
||||
ABGR8 src(int x, int y) {
|
||||
return packUnorm4x8(texelFetch(samp0, ivec2(x, y), 0));
|
||||
}
|
||||
|
||||
void dst(int x, int y, ABGR8 value) {
|
||||
imageStore(dst_image, ivec2(x, y), unpackUnorm4x8(value));
|
||||
}
|
||||
|
||||
uint luma(ABGR8 C) {
|
||||
uint alpha = (C & 0xFF000000u) >> 24;
|
||||
return (((C & 0x00FF0000u) >> 16) + ((C & 0x0000FF00u) >> 8) + (C & 0x000000FFu) + 1u) * (256u - alpha);
|
||||
}
|
||||
|
||||
bool all_eq2(ABGR8 B, ABGR8 A0, ABGR8 A1) {
|
||||
return ((B ^ A0) | (B ^ A1)) == 0u;
|
||||
}
|
||||
|
||||
bool all_eq3(ABGR8 B, ABGR8 A0, ABGR8 A1, ABGR8 A2) {
|
||||
return ((B ^ A0) | (B ^ A1) | (B ^ A2)) == 0u;
|
||||
}
|
||||
|
||||
bool all_eq4(ABGR8 B, ABGR8 A0, ABGR8 A1, ABGR8 A2, ABGR8 A3) {
|
||||
return ((B ^ A0) | (B ^ A1) | (B ^ A2) | (B ^ A3)) == 0u;
|
||||
}
|
||||
|
||||
bool any_eq3(ABGR8 B, ABGR8 A0, ABGR8 A1, ABGR8 A2) {
|
||||
return B == A0 || B == A1 || B == A2;
|
||||
}
|
||||
|
||||
bool none_eq2(ABGR8 B, ABGR8 A0, ABGR8 A1) {
|
||||
return (B != A0) && (B != A1);
|
||||
}
|
||||
|
||||
bool none_eq4(ABGR8 B, ABGR8 A0, ABGR8 A1, ABGR8 A2, ABGR8 A3) {
|
||||
return B != A0 && B != A1 && B != A2 && B != A3;
|
||||
}
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
void main () {
|
||||
// EPX first falls back to Nearest Neighbour
|
||||
int srcX = int(gl_GlobalInvocationID.x);
|
||||
int srcY = int(gl_GlobalInvocationID.y);
|
||||
if (srcX >= src_size.x || srcY >= src_size.y)
|
||||
return;
|
||||
|
||||
ABGR8 A = src(srcX - 1, srcY - 1), B = src(srcX, srcY - 1), C = src(srcX + 1, srcY - 1);
|
||||
ABGR8 D = src(srcX - 1, srcY + 0), E = src(srcX, srcY + 0), F = src(srcX + 1, srcY + 0);
|
||||
ABGR8 G = src(srcX - 1, srcY + 1), H = src(srcX, srcY + 1), I = src(srcX + 1, srcY + 1);
|
||||
|
||||
ABGR8 J = E, K = E, L = E, M = E;
|
||||
|
||||
if (((A ^ E) | (B ^ E) | (C ^ E) | (D ^ E) | (F ^ E) | (G ^ E) | (H ^ E) | (I ^ E)) != 0u) {
|
||||
ABGR8 P = src(srcX, srcY - 2), S = src(srcX, srcY + 2);
|
||||
ABGR8 Q = src(srcX - 2, srcY), R = src(srcX + 2, srcY);
|
||||
ABGR8 Bl = luma(B), Dl = luma(D), El = luma(E), Fl = luma(F), Hl = luma(H);
|
||||
|
||||
// 1:1 slope rules
|
||||
if ((D == B && D != H && D != F) && (El >= Dl || E == A) && any_eq3(E, A, C, G) && ((El < Dl) || A != D || E != P || E != Q)) J = D;
|
||||
if ((B == F && B != D && B != H) && (El >= Bl || E == C) && any_eq3(E, A, C, I) && ((El < Bl) || C != B || E != P || E != R)) K = B;
|
||||
if ((H == D && H != F && H != B) && (El >= Hl || E == G) && any_eq3(E, A, G, I) && ((El < Hl) || G != H || E != S || E != Q)) L = H;
|
||||
if ((F == H && F != B && F != D) && (El >= Fl || E == I) && any_eq3(E, C, G, I) && ((El < Fl) || I != H || E != R || E != S)) M = F;
|
||||
|
||||
// Intersection rules
|
||||
if ((E != F && all_eq4(E, C, I, D, Q) && all_eq2(F, B, H)) && (F != src(srcX + 3, srcY))) K = M = F;
|
||||
if ((E != D && all_eq4(E, A, G, F, R) && all_eq2(D, B, H)) && (D != src(srcX - 3, srcY))) J = L = D;
|
||||
if ((E != H && all_eq4(E, G, I, B, P) && all_eq2(H, D, F)) && (H != src(srcX, srcY + 3))) L = M = H;
|
||||
if ((E != B && all_eq4(E, A, C, H, S) && all_eq2(B, D, F)) && (B != src(srcX, srcY - 3))) J = K = B;
|
||||
if (Bl < El && all_eq4(E, G, H, I, S) && none_eq4(E, A, D, C, F)) J = K = B;
|
||||
if (Hl < El && all_eq4(E, A, B, C, P) && none_eq4(E, D, G, I, F)) L = M = H;
|
||||
if (Fl < El && all_eq4(E, A, D, G, Q) && none_eq4(E, B, C, I, H)) K = M = F;
|
||||
if (Dl < El && all_eq4(E, C, F, I, R) && none_eq4(E, B, A, G, H)) J = L = D;
|
||||
|
||||
// 2:1 slope rules
|
||||
if (H != B) {
|
||||
if (H != A && H != E && H != C) {
|
||||
if (all_eq3(H, G, F, R) && none_eq2(H, D, src(srcX + 2, srcY - 1))) L = M;
|
||||
if (all_eq3(H, I, D, Q) && none_eq2(H, F, src(srcX - 2, srcY - 1))) M = L;
|
||||
}
|
||||
|
||||
if (B != I && B != G && B != E) {
|
||||
if (all_eq3(B, A, F, R) && none_eq2(B, D, src(srcX + 2, srcY + 1))) J = K;
|
||||
if (all_eq3(B, C, D, Q) && none_eq2(B, F, src(srcX - 2, srcY + 1))) K = J;
|
||||
}
|
||||
} // H !== B
|
||||
|
||||
if (F != D) {
|
||||
if (D != I && D != E && D != C) {
|
||||
if (all_eq3(D, A, H, S) && none_eq2(D, B, src(srcX + 1, srcY + 2))) J = L;
|
||||
if (all_eq3(D, G, B, P) && none_eq2(D, H, src(srcX + 1, srcY - 2))) L = J;
|
||||
}
|
||||
|
||||
if (F != E && F != A && F != G) {
|
||||
if (all_eq3(F, C, H, S) && none_eq2(F, B, src(srcX - 1, srcY + 2))) K = M;
|
||||
if (all_eq3(F, I, B, P) && none_eq2(F, H, src(srcX - 1, srcY - 2))) M = K;
|
||||
}
|
||||
} // F !== D
|
||||
} // not constant
|
||||
|
||||
// Write four pixels at once
|
||||
dst(srcX * 2, srcY * 2, J);
|
||||
dst(srcX * 2 + 1, srcY * 2, K);
|
||||
dst(srcX * 2, srcY * 2 + 1, L);
|
||||
dst(srcX * 2 + 1, srcY * 2 + 1, M);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
// EPX.glc
|
||||
// Copyright 2020 Morgan McGuire & Mara Gagiu,
|
||||
// provided under the Open Source MIT license https://opensource.org/licenses/MIT
|
||||
|
||||
// Implementation of Eric Johnston and Andrea Mazzoleni's
|
||||
// EPX aka Scale2X algorithm based on https://www.scale2x.it/algorithm
|
||||
|
||||
#define ABGR8 uint
|
||||
|
||||
UNIFORM_BLOCK_LAYOUT uniform UBOBlock {
|
||||
ivec2 src_size;
|
||||
ivec2 dst_size;
|
||||
};
|
||||
|
||||
TEXTURE_LAYOUT(0) uniform sampler2D samp0;
|
||||
IMAGE_LAYOUT(0, rgba8) uniform restrict writeonly image2D dst_image;
|
||||
|
||||
ABGR8 src(int x, int y) {
|
||||
return packUnorm4x8(texelFetch(samp0, ivec2(x, y), 0));
|
||||
}
|
||||
|
||||
void dst(int x, int y, ABGR8 value) {
|
||||
imageStore(dst_image, ivec2(x, y), unpackUnorm4x8(value));
|
||||
}
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
void main () {
|
||||
// EPX first falls back to Nearest Neighbour
|
||||
int srcX = int(gl_GlobalInvocationID.x);
|
||||
int srcY = int(gl_GlobalInvocationID.y);
|
||||
if (srcX >= src_size.x || srcY >= src_size.y)
|
||||
return;
|
||||
|
||||
ABGR8 E = src(srcX, srcY);
|
||||
ABGR8 J = E, K = E, L = E, M = E;
|
||||
|
||||
ABGR8 B = src(srcX + 0, srcY - 1);
|
||||
ABGR8 D = src(srcX - 1, srcY + 0);
|
||||
ABGR8 F = src(srcX + 1, srcY + 0);
|
||||
ABGR8 H = src(srcX + 0, srcY + 1);
|
||||
|
||||
if (D == B && B != F && D != H) J = D;
|
||||
if (B == F && D != F && H != F) K = F;
|
||||
if (H == D && F != D && B != D) L = D;
|
||||
if (H == F && D != H && B != F) M = F;
|
||||
|
||||
// Write four pixels at once
|
||||
dst(srcX * 2, srcY * 2, J);
|
||||
dst(srcX * 2 + 1, srcY * 2, K);
|
||||
dst(srcX * 2, srcY * 2 + 1, L);
|
||||
dst(srcX * 2 + 1, srcY * 2 + 1, M);
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
layout(location = 0) in VertexData {
|
||||
vec2 v_tex0;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec4 dest;
|
||||
|
||||
TEXTURE_LAYOUT(0) uniform sampler2D samp0;
|
||||
|
||||
vec4 SrcGet(vec2 uv)
|
||||
{
|
||||
return texelFetch(samp0, ivec2(uv), 0);
|
||||
}
|
||||
|
||||
// XBR.pix
|
||||
// Copyright 2020 Morgan McGuire & Mara Gagiu,
|
||||
// provided under the Open Source MIT license https://opensource.org/licenses/MIT
|
||||
|
||||
#define XBR_Y_WEIGHT 48.0
|
||||
#define XBR_EQ_THRESHOLD 15.0
|
||||
#define XBR_LV1_COEFFICIENT 0.5
|
||||
#define XBR_LV2_COEFFICIENT 2.0
|
||||
// END PARAMETERS //
|
||||
|
||||
|
||||
// XBR GLSL implementation source:
|
||||
// https://github.com/libretro/glsl-shaders/blob/master/xbr/shaders/xbr-lv2.glsl
|
||||
/*
|
||||
Hyllian's xBR-lv2 Shader
|
||||
Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
|
||||
|
||||
*/
|
||||
|
||||
// Uncomment just one of the three params below to choose the corner detection
|
||||
#define CORNER_A
|
||||
//#define CORNER_B
|
||||
//#define CORNER_C
|
||||
//#define CORNER_D
|
||||
|
||||
#ifndef CORNER_A
|
||||
#define SMOOTH_TIPS
|
||||
#endif
|
||||
|
||||
#define XBR_SCALE 2.0
|
||||
#define lv2_cf XBR_LV2_COEFFICIENT
|
||||
//=================================================================================
|
||||
// XBR Helper Functions
|
||||
//=================================================================================
|
||||
const float coef = 2.0;
|
||||
const vec3 rgbw = vec3(14.352, 28.176, 5.472);
|
||||
const vec4 eq_threshold = vec4(15.0, 15.0, 15.0, 15.0);
|
||||
|
||||
const vec4 delta = vec4(1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
const vec4 delta_l = vec4(0.5/XBR_SCALE, 1.0/XBR_SCALE, 0.5/XBR_SCALE, 1.0/XBR_SCALE);
|
||||
const vec4 delta_u = delta_l.yxwz;
|
||||
|
||||
const vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 Bo = vec4( 1.0, 1.0, -1.0,-1.0 );
|
||||
const vec4 Co = vec4( 1.5, 0.5, -0.5, 0.5 );
|
||||
const vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 Bx = vec4( 0.5, 2.0, -0.5,-2.0 );
|
||||
const vec4 Cx = vec4( 1.0, 1.0, -0.5, 0.0 );
|
||||
const vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
|
||||
const vec4 By = vec4( 2.0, 0.5, -2.0,-0.5 );
|
||||
const vec4 Cy = vec4( 2.0, 0.0, -1.0, 0.5 );
|
||||
const vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);
|
||||
|
||||
// Difference between vector components.
|
||||
vec4 df(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(abs(A-B));
|
||||
}
|
||||
|
||||
// Compare two vectors and return their components are different.
|
||||
vec4 diff(vec4 A, vec4 B)
|
||||
{
|
||||
return vec4(notEqual(A, B));
|
||||
}
|
||||
|
||||
// Determine if two vector components are equal based on a threshold.
|
||||
vec4 eq(vec4 A, vec4 B)
|
||||
{
|
||||
return (step(df(A, B), vec4(XBR_EQ_THRESHOLD)));
|
||||
}
|
||||
|
||||
// Determine if two vector components are NOT equal based on a threshold.
|
||||
vec4 neq(vec4 A, vec4 B)
|
||||
{
|
||||
return (vec4(1.0, 1.0, 1.0, 1.0) - eq(A, B));
|
||||
}
|
||||
|
||||
// Weighted distance.
|
||||
vec4 wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
|
||||
{
|
||||
return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
|
||||
}
|
||||
|
||||
float c_df(vec3 c1, vec3 c2)
|
||||
{
|
||||
vec3 df = abs(c1 - c2);
|
||||
return df.r + df.g + df.b;
|
||||
}
|
||||
|
||||
vec4 XBR()
|
||||
{
|
||||
vec4 proxy_dest = vec4(0, 0, 0, 1);
|
||||
ivec2 tex_fetch_coords = ivec2(gl_FragCoord.xy / 2.0);
|
||||
ivec2 tex_coords = ivec2(gl_FragCoord.xy);
|
||||
|
||||
|
||||
|
||||
vec4 edri, edr, edr_l, edr_u, px; // px = pixel, edr = edge detection rule
|
||||
vec4 irlv0, irlv1, irlv2l, irlv2u, block_3d;
|
||||
vec4 fx, fx_l, fx_u; // inequations of straight lines.
|
||||
|
||||
vec2 fp = fract(gl_FragCoord.xy / 2.0);
|
||||
|
||||
vec3 A1 = SrcGet(tex_fetch_coords + ivec2(-1, -2)).xyz;
|
||||
vec3 B1 = SrcGet(tex_fetch_coords + ivec2( 0, -2)).xyz;
|
||||
vec3 C1 = SrcGet(tex_fetch_coords + ivec2(+1, -2)).xyz;
|
||||
vec3 A = SrcGet(tex_fetch_coords + ivec2(-1, -1)).xyz;
|
||||
vec3 B = SrcGet(tex_fetch_coords + ivec2( 0, -1)).xyz;
|
||||
vec3 C = SrcGet(tex_fetch_coords + ivec2(+1, -1)).xyz;
|
||||
vec3 D = SrcGet(tex_fetch_coords + ivec2(-1, 0)).xyz;
|
||||
vec4 Eo = SrcGet(tex_fetch_coords);
|
||||
vec3 E = Eo.xyz;
|
||||
vec3 F = SrcGet(tex_fetch_coords + ivec2(+1, 0)).xyz;
|
||||
vec3 G = SrcGet(tex_fetch_coords + ivec2(-1, +1)).xyz;
|
||||
vec3 H = SrcGet(tex_fetch_coords + ivec2( 0, +1)).xyz;
|
||||
vec3 I = SrcGet(tex_fetch_coords + ivec2(+1, +1)).xyz;
|
||||
vec3 G5 = SrcGet(tex_fetch_coords + ivec2(-1, +2)).xyz;
|
||||
vec3 H5 = SrcGet(tex_fetch_coords + ivec2( 0, +2) ).xyz;
|
||||
vec3 I5 = SrcGet(tex_fetch_coords + ivec2(+1, +2)).xyz;
|
||||
vec3 A0 = SrcGet(tex_fetch_coords + ivec2(-2, -1)).xyz;
|
||||
vec3 D0 = SrcGet(tex_fetch_coords + ivec2(-2, 0)).xyz;
|
||||
vec3 G0 = SrcGet(tex_fetch_coords + ivec2(-2, +1)).xyz;
|
||||
vec3 C4 = SrcGet(tex_fetch_coords + ivec2(+2, -1)).xyz;
|
||||
vec3 F4 = SrcGet(tex_fetch_coords + ivec2(+2, 0)).xyz;
|
||||
vec3 I4 = SrcGet(tex_fetch_coords + ivec2(+2, +1)).xyz;
|
||||
|
||||
vec4 b = vec4(dot(B ,rgbw), dot(D ,rgbw), dot(H ,rgbw), dot(F ,rgbw));
|
||||
vec4 c = vec4(dot(C ,rgbw), dot(A ,rgbw), dot(G ,rgbw), dot(I ,rgbw));
|
||||
vec4 d = b.yzwx;
|
||||
vec4 e = vec4(dot(E,rgbw));
|
||||
vec4 f = b.wxyz;
|
||||
vec4 g = c.zwxy;
|
||||
vec4 h = b.zwxy;
|
||||
vec4 i = c.wxyz;
|
||||
vec4 i4 = vec4(dot(I4,rgbw), dot(C1,rgbw), dot(A0,rgbw), dot(G5,rgbw));
|
||||
vec4 i5 = vec4(dot(I5,rgbw), dot(C4,rgbw), dot(A1,rgbw), dot(G0,rgbw));
|
||||
vec4 h5 = vec4(dot(H5,rgbw), dot(F4,rgbw), dot(B1,rgbw), dot(D0,rgbw));
|
||||
vec4 f4 = h5.yzwx;
|
||||
|
||||
// These inequations define the line below which interpolation occurs.
|
||||
fx = (Ao*fp.y+Bo*fp.x);
|
||||
fx_l = (Ax*fp.y+Bx*fp.x);
|
||||
fx_u = (Ay*fp.y+By*fp.x);
|
||||
|
||||
irlv1 = irlv0 = diff(e,f) * diff(e,h);
|
||||
|
||||
#ifdef CORNER_B
|
||||
|
||||
// E1/K case (X odd, Y even)
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) );
|
||||
|
||||
#endif
|
||||
#ifdef CORNER_D
|
||||
|
||||
// E3/M case (X odd, Y odd)
|
||||
vec4 c1 = i4.yzwx;
|
||||
vec4 g0 = i5.wxyz;
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(h,d) + eq(e,i) * neq(f,i4) * neq(h,i5) + eq(e,g) + eq(e,c) ) * (diff(f,f4) * diff(f,i) + diff(h,h5) * diff(h,i) + diff(h,g) + diff(f,c) + eq(b,c1) * eq(d,g0)));
|
||||
|
||||
#endif
|
||||
#ifdef CORNER_C
|
||||
|
||||
irlv1 = (irlv0 * ( neq(f,b) * neq(f,c) + neq(h,d) * neq(h,g) + eq(e,i) * (neq(f,f4) * neq(f,i4) + neq(h,h5) * neq(h,i5)) + eq(e,g) + eq(e,c)) );
|
||||
|
||||
#endif
|
||||
|
||||
irlv2l = diff(e,g) * diff(d,g);
|
||||
irlv2u = diff(e,c) * diff(b,c);
|
||||
|
||||
vec4 fx45i = clamp((fx + delta -Co - Ci)/(2.0*delta ), 0.0, 1.0);
|
||||
vec4 fx45 = clamp((fx + delta -Co )/(2.0*delta ), 0.0, 1.0);
|
||||
vec4 fx30 = clamp((fx_l + delta_l -Cx )/(2.0*delta_l), 0.0, 1.0);
|
||||
vec4 fx60 = clamp((fx_u + delta_u -Cy )/(2.0*delta_u), 0.0, 1.0);
|
||||
|
||||
vec4 wd1 = wd( e, c, g, i, h5, f4, h, f);
|
||||
vec4 wd2 = wd( h, d, i5, f, i4, b, e, i);
|
||||
|
||||
edri = step(wd1, wd2) * irlv0;
|
||||
edr = step(wd1 + vec4(0.1, 0.1, 0.1, 0.1), wd2) * step(vec4(0.5, 0.5, 0.5, 0.5), irlv1);
|
||||
edr_l = step( lv2_cf*df(f,g), df(h,c) ) * irlv2l * edr;
|
||||
edr_u = step( lv2_cf*df(h,c), df(f,g) ) * irlv2u * edr;
|
||||
|
||||
fx45 = edr * fx45;
|
||||
fx30 = edr_l * fx30;
|
||||
fx60 = edr_u * fx60;
|
||||
fx45i = edri * fx45i;
|
||||
|
||||
px = step(df(e,f), df(e,h));
|
||||
|
||||
#ifdef SMOOTH_TIPS
|
||||
//vec4 maximos = max(max(fx30, fx60), max(fx45, fx45i));
|
||||
#endif
|
||||
#ifndef SMOOTH_TIPS
|
||||
vec4 maximos = max(max(fx30, fx60), fx45);
|
||||
#endif
|
||||
|
||||
vec3 res1 = E;
|
||||
res1 = mix(res1, mix(H, F, px.x), maximos.x);
|
||||
res1 = mix(res1, mix(B, D, px.z), maximos.z);
|
||||
|
||||
vec3 res2 = E;
|
||||
res2 = mix(res2, mix(F, B, px.y), maximos.y);
|
||||
res2 = mix(res2, mix(D, H, px.w), maximos.w);
|
||||
|
||||
vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2)));
|
||||
|
||||
proxy_dest.rgb = res;
|
||||
proxy_dest.a = Eo.a;
|
||||
return proxy_dest;
|
||||
}
|
||||
|
||||
void main () {
|
||||
dest = XBR();
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
layout(location = 0) out VertexData {
|
||||
vec2 v_tex0;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
v_tex0 = vec2(float((gl_VertexIndex << 1) & 2), float(gl_VertexIndex & 2u));
|
||||
gl_Position = vec4(v_tex0 * vec2(2.0f, -2.0f) + vec2(-1.0f, 1.0f), 0.0f, 1.0f);
|
||||
#if API_OPENGL || API_OPENGL_ES || API_VULKAN
|
||||
gl_Position.y = -gl_Position.y;
|
||||
#endif
|
||||
}
|
||||
@@ -2563,6 +2563,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
</pre>
|
||||
|
||||
<h3>Texture Decompression Routines</h3>
|
||||
<pre>
|
||||
Copyright (C) 2009 Benjamin Dobell, Glass Echidna
|
||||
Copyright (C) 2012 - 2022, Matthäus G. "Anteru" Chajdas (https://anteru.net)
|
||||
Copyright (C) 2020 Richard Geldreich, Jr.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
</pre>
|
||||
|
||||
Some shaders provided with the application are sourced from:
|
||||
<ul>
|
||||
<li><a href="https://github.com/Matsilagi/RSRetroArch/">https://github.com/Matsilagi/RSRetroArch/</a></li>
|
||||
|
||||
@@ -230,7 +230,7 @@ STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri
|
||||
#define stbsp__uint16 unsigned short
|
||||
|
||||
#ifndef stbsp__uintptr
|
||||
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__)
|
||||
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) || (defined(__riscv) && __riscv_xlen == 64)
|
||||
#define stbsp__uintptr stbsp__uint64
|
||||
#else
|
||||
#define stbsp__uintptr stbsp__uint32
|
||||
|
||||
@@ -82,4 +82,9 @@
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="$(Configuration.Contains(Devel))">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEVEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
@@ -57,6 +57,14 @@
|
||||
<Configuration>Release-Clang</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Devel-Clang|ARM64">
|
||||
<Configuration>Devel-Clang</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Devel-Clang|x64">
|
||||
<Configuration>Devel-Clang</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
|
||||
@@ -93,6 +93,7 @@ enum {
|
||||
RC_CONSOLE_NINTENDO_DSI = 78,
|
||||
RC_CONSOLE_TI83 = 79,
|
||||
RC_CONSOLE_UZEBOX = 80,
|
||||
RC_CONSOLE_FAMICOM_DISK_SYSTEM = 81,
|
||||
|
||||
RC_CONSOLE_HUBS = 100,
|
||||
RC_CONSOLE_EVENTS = 101,
|
||||
|
||||
@@ -46,7 +46,6 @@ typedef struct rc_runtime_trigger_t {
|
||||
rc_memref_t* invalid_memref;
|
||||
uint8_t md5[16];
|
||||
int32_t serialized_size;
|
||||
uint8_t owns_memrefs;
|
||||
}
|
||||
rc_runtime_trigger_t;
|
||||
|
||||
@@ -58,16 +57,13 @@ typedef struct rc_runtime_lboard_t {
|
||||
rc_memref_t* invalid_memref;
|
||||
uint8_t md5[16];
|
||||
uint32_t serialized_size;
|
||||
uint8_t owns_memrefs;
|
||||
}
|
||||
rc_runtime_lboard_t;
|
||||
|
||||
typedef struct rc_runtime_richpresence_t {
|
||||
rc_richpresence_t* richpresence;
|
||||
void* buffer;
|
||||
struct rc_runtime_richpresence_t* previous;
|
||||
uint8_t md5[16];
|
||||
uint8_t owns_memrefs;
|
||||
}
|
||||
rc_runtime_richpresence_t;
|
||||
|
||||
@@ -82,11 +78,7 @@ typedef struct rc_runtime_t {
|
||||
|
||||
rc_runtime_richpresence_t* richpresence;
|
||||
|
||||
rc_memref_t* memrefs;
|
||||
rc_memref_t** next_memref;
|
||||
|
||||
rc_value_t* variables;
|
||||
rc_value_t** next_variable;
|
||||
struct rc_memrefs_t* memrefs;
|
||||
|
||||
uint8_t owns_self;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef struct rc_value_t rc_value_t;
|
||||
* num_bytes is greater than 1, the value is read in little-endian from
|
||||
* memory.
|
||||
*/
|
||||
typedef uint32_t(RC_CCONV *rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud);
|
||||
typedef uint32_t(RC_CCONV* rc_peek_t)(uint32_t address, uint32_t num_bytes, void* ud);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Memory References |
|
||||
@@ -70,15 +70,14 @@ typedef struct rc_memref_value_t {
|
||||
/* The last differing value of this memory reference. */
|
||||
uint32_t prior;
|
||||
|
||||
/* The size of the value. */
|
||||
/* The size of the value. (RC_MEMSIZE_*) */
|
||||
uint8_t size;
|
||||
/* True if the value changed this frame. */
|
||||
uint8_t changed;
|
||||
/* The value type of the value (for variables) */
|
||||
/* The value type of the value. (RC_VALUE_TYPE_*) */
|
||||
uint8_t type;
|
||||
/* True if the reference will be used in indirection.
|
||||
* NOTE: This is actually a property of the rc_memref_t, but we put it here to save space */
|
||||
uint8_t is_indirect;
|
||||
/* The type of memref (RC_MEMREF_TYPE_*) */
|
||||
uint8_t memref_type;
|
||||
}
|
||||
rc_memref_value_t;
|
||||
|
||||
@@ -88,9 +87,6 @@ struct rc_memref_t {
|
||||
|
||||
/* The memory address of this variable. */
|
||||
uint32_t address;
|
||||
|
||||
/* The next memory reference in the chain. */
|
||||
rc_memref_t* next;
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
@@ -125,11 +121,14 @@ typedef struct rc_operand_t {
|
||||
int luafunc;
|
||||
} value;
|
||||
|
||||
/* specifies which member of the value union is being used */
|
||||
/* specifies which member of the value union is being used (RC_OPERAND_*) */
|
||||
uint8_t type;
|
||||
|
||||
/* the actual RC_MEMSIZE of the operand - memref.size may differ */
|
||||
/* the RC_MEMSIZE of the operand specified in the condition definition - memref.size may differ */
|
||||
uint8_t size;
|
||||
|
||||
/* specifies how to read the memref for some types (RC_OPERAND_*) */
|
||||
uint8_t memref_access_type;
|
||||
}
|
||||
rc_operand_t;
|
||||
|
||||
@@ -141,23 +140,16 @@ RC_EXPORT int RC_CCONV rc_operand_is_memref(const rc_operand_t* operand);
|
||||
|
||||
/* types */
|
||||
enum {
|
||||
/* NOTE: this enum is ordered to optimize the switch statements in rc_test_condset_internal. the values may change between releases */
|
||||
|
||||
/* non-combining conditions (third switch) */
|
||||
RC_CONDITION_STANDARD, /* this should always be 0 */
|
||||
RC_CONDITION_PAUSE_IF,
|
||||
RC_CONDITION_RESET_IF,
|
||||
RC_CONDITION_MEASURED_IF,
|
||||
RC_CONDITION_TRIGGER,
|
||||
RC_CONDITION_MEASURED, /* measured also appears in the first switch, so place it at the border between them */
|
||||
|
||||
/* modifiers (first switch) */
|
||||
RC_CONDITION_ADD_SOURCE, /* everything from this point on affects the condition after it */
|
||||
RC_CONDITION_MEASURED,
|
||||
RC_CONDITION_ADD_SOURCE,
|
||||
RC_CONDITION_SUB_SOURCE,
|
||||
RC_CONDITION_ADD_ADDRESS,
|
||||
RC_CONDITION_REMEMBER,
|
||||
|
||||
/* logic flags (second switch) */
|
||||
RC_CONDITION_ADD_HITS,
|
||||
RC_CONDITION_SUB_HITS,
|
||||
RC_CONDITION_RESET_NEXT_IF,
|
||||
@@ -180,7 +172,10 @@ enum {
|
||||
RC_OPERATOR_XOR,
|
||||
RC_OPERATOR_MOD,
|
||||
RC_OPERATOR_ADD,
|
||||
RC_OPERATOR_SUB
|
||||
RC_OPERATOR_SUB,
|
||||
|
||||
RC_OPERATOR_SUB_PARENT, /* internal use */
|
||||
RC_OPERATOR_INDIRECT_READ /* internal use */
|
||||
};
|
||||
|
||||
typedef struct rc_condition_t rc_condition_t;
|
||||
@@ -204,9 +199,6 @@ struct rc_condition_t {
|
||||
/* The comparison operator to use. (RC_OPERATOR_*) */
|
||||
uint8_t oper; /* operator is a reserved word in C++. */
|
||||
|
||||
/* Set if the condition needs to processed as part of the "check if paused" pass. (bool) */
|
||||
uint8_t pause;
|
||||
|
||||
/* Whether or not the condition evaluated true on the last check. (bool) */
|
||||
uint8_t is_true;
|
||||
|
||||
@@ -224,17 +216,32 @@ struct rc_condset_t {
|
||||
/* The next condition set in the chain. */
|
||||
rc_condset_t* next;
|
||||
|
||||
/* The list of conditions in this condition set. */
|
||||
/* The first condition in this condition set. Then follow ->next chain. */
|
||||
rc_condition_t* conditions;
|
||||
|
||||
/* True if any condition in the set is a pause condition. */
|
||||
uint8_t has_pause;
|
||||
/* The number of pause conditions in this condition set. */
|
||||
/* The first pause condition is at "this + RC_ALIGN(sizeof(this)). */
|
||||
uint16_t num_pause_conditions;
|
||||
|
||||
/* The number of reset conditions in this condition set. */
|
||||
uint16_t num_reset_conditions;
|
||||
|
||||
/* The number of hittarget conditions in this condition set. */
|
||||
uint16_t num_hittarget_conditions;
|
||||
|
||||
/* The number of non-hittarget measured conditions in this condition set. */
|
||||
uint16_t num_measured_conditions;
|
||||
|
||||
/* The number of other conditions in this condition set. */
|
||||
uint16_t num_other_conditions;
|
||||
|
||||
/* The number of indirect conditions in this condition set. */
|
||||
uint16_t num_indirect_conditions;
|
||||
|
||||
/* True if any condition in the set is a pause condition. */
|
||||
uint8_t has_pause; /* DEPRECATED - just check num_pause_conditions != 0 */
|
||||
/* True if the set is currently paused. */
|
||||
uint8_t is_paused;
|
||||
|
||||
/* True if the set has indirect memory references. */
|
||||
uint8_t has_indirect_memrefs;
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
@@ -259,9 +266,6 @@ struct rc_trigger_t {
|
||||
/* The list of sub condition sets in this test. */
|
||||
rc_condset_t* alternative;
|
||||
|
||||
/* The memory references required by the trigger. */
|
||||
rc_memref_t* memrefs;
|
||||
|
||||
/* The current state of the MEASURED condition. */
|
||||
uint32_t measured_value;
|
||||
|
||||
@@ -274,11 +278,11 @@ struct rc_trigger_t {
|
||||
/* True if at least one condition has a non-zero hit count */
|
||||
uint8_t has_hits;
|
||||
|
||||
/* True if at least one condition has a non-zero required hit count */
|
||||
uint8_t has_required_hits;
|
||||
|
||||
/* True if the measured value should be displayed as a percentage */
|
||||
uint8_t measured_as_percent;
|
||||
|
||||
/* True if the trigger has its own rc_memrefs_t */
|
||||
uint8_t has_memrefs;
|
||||
};
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_trigger_size(const char* memaddr);
|
||||
@@ -297,11 +301,11 @@ struct rc_value_t {
|
||||
/* The current value of the variable. */
|
||||
rc_memref_value_t value;
|
||||
|
||||
/* The list of conditions to evaluate. */
|
||||
rc_condset_t* conditions;
|
||||
/* True if the value has its own rc_memrefs_t */
|
||||
uint8_t has_memrefs;
|
||||
|
||||
/* The memory references required by the variable. */
|
||||
rc_memref_t* memrefs;
|
||||
/* The list of possible values (traverse next chain, pick max). */
|
||||
rc_condset_t* conditions;
|
||||
|
||||
/* The name of the variable. */
|
||||
const char* name;
|
||||
@@ -335,9 +339,9 @@ struct rc_lboard_t {
|
||||
rc_trigger_t cancel;
|
||||
rc_value_t value;
|
||||
rc_value_t* progress;
|
||||
rc_memref_t* memrefs;
|
||||
|
||||
uint8_t state;
|
||||
uint8_t has_memrefs;
|
||||
};
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_lboard_size(const char* memaddr);
|
||||
@@ -406,7 +410,7 @@ struct rc_richpresence_display_part_t {
|
||||
rc_richpresence_display_part_t* next;
|
||||
const char* text;
|
||||
rc_richpresence_lookup_t* lookup;
|
||||
rc_memref_value_t *value;
|
||||
rc_operand_t value;
|
||||
uint8_t display_type;
|
||||
};
|
||||
|
||||
@@ -416,13 +420,14 @@ struct rc_richpresence_display_t {
|
||||
rc_trigger_t trigger;
|
||||
rc_richpresence_display_t* next;
|
||||
rc_richpresence_display_part_t* display;
|
||||
uint8_t has_required_hits;
|
||||
};
|
||||
|
||||
struct rc_richpresence_t {
|
||||
rc_richpresence_display_t* first_display;
|
||||
rc_richpresence_lookup_t* first_lookup;
|
||||
rc_memref_t* memrefs;
|
||||
rc_value_t* variables;
|
||||
rc_value_t* values;
|
||||
uint8_t has_memrefs;
|
||||
};
|
||||
|
||||
RC_EXPORT int RC_CCONV rc_richpresence_size(const char* script);
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
<ClInclude Include="src\rc_version.h" />
|
||||
<ClInclude Include="src\rhash\md5.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="src\rcheevos\rc_runtime_types.natvis" />
|
||||
<Natvis Include="src\rc_client_types.natvis" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -138,4 +138,10 @@
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="src\rc_client_types.natvis" />
|
||||
<Natvis Include="src\rcheevos\rc_runtime_types.natvis">
|
||||
<Filter>rcheevos</Filter>
|
||||
</Natvis>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -91,6 +91,70 @@ static void rc_client_award_achievement_retry(rc_client_scheduled_callback_data_
|
||||
static int rc_client_is_award_achievement_pending(const rc_client_t* client, uint32_t achievement_id);
|
||||
static void rc_client_submit_leaderboard_entry_retry(rc_client_scheduled_callback_data_t* callback_data, rc_client_t* client, rc_clock_t now);
|
||||
|
||||
/* ===== natvis extensions ===== */
|
||||
|
||||
typedef struct __rc_client_achievement_state_enum_t { uint8_t value; } __rc_client_achievement_state_enum_t;
|
||||
typedef struct __rc_client_achievement_category_enum_t { uint8_t value; } __rc_client_achievement_category_enum_t;
|
||||
typedef struct __rc_client_achievement_type_enum_t { uint8_t value; } __rc_client_achievement_type_enum_t;
|
||||
typedef struct __rc_client_achievement_bucket_enum_t { uint8_t value; } __rc_client_achievement_bucket_enum_t;
|
||||
typedef struct __rc_client_achievement_unlocked_enum_t { uint8_t value; } __rc_client_achievement_unlocked_enum_t;
|
||||
typedef struct __rc_client_leaderboard_state_enum_t { uint8_t value; } __rc_client_leaderboard_state_enum_t;
|
||||
typedef struct __rc_client_leaderboard_format_enum_t { uint8_t value; } __rc_client_leaderboard_format_enum_t;
|
||||
typedef struct __rc_client_log_level_enum_t { uint8_t value; } __rc_client_log_level_enum_t;
|
||||
typedef struct __rc_client_event_type_enum_t { uint8_t value; } __rc_client_event_type_enum_t;
|
||||
typedef struct __rc_client_load_game_state_enum_t { uint8_t value; } __rc_client_load_game_state_enum_t;
|
||||
typedef struct __rc_client_user_state_enum_t { uint8_t value; } __rc_client_user_state_enum_t;
|
||||
typedef struct __rc_client_mastery_state_enum_t { uint8_t value; } __rc_client_mastery_state_enum_t;
|
||||
typedef struct __rc_client_spectator_mode_enum_t { uint8_t value; } __rc_client_spectator_mode_enum_t;
|
||||
typedef struct __rc_client_disconnect_enum_t { uint8_t value; } __rc_client_disconnect_enum_t;
|
||||
typedef struct __rc_client_leaderboard_tracker_list_t { rc_client_leaderboard_tracker_info_t* first; } __rc_client_leaderboard_tracker_list_t;
|
||||
typedef struct __rc_client_subset_info_list_t { rc_client_subset_info_t* first; } __rc_client_subset_info_list_t;
|
||||
typedef struct __rc_client_media_hash_list_t { rc_client_media_hash_t* first; } __rc_client_media_hash_list_t;
|
||||
typedef struct __rc_client_subset_info_achievements_list_t { rc_client_subset_info_t info; } __rc_client_subset_info_achievements_list_t;
|
||||
typedef struct __rc_client_subset_info_leaderboards_list_t { rc_client_subset_info_t info; } __rc_client_subset_info_leaderboards_list_t;
|
||||
typedef struct __rc_client_scheduled_callback_list_t { rc_client_state_t state; } __rc_client_scheduled_callback_list_t;
|
||||
typedef struct __rc_client_game_hash_list_t { rc_client_t client; } __rc_client_game_hash_list_t;
|
||||
|
||||
static void rc_client_natvis_helper(const rc_client_event_t* event, rc_client_t* client)
|
||||
{
|
||||
struct natvis_extensions {
|
||||
__rc_client_achievement_state_enum_t achievement_state;
|
||||
__rc_client_achievement_category_enum_t achievement_category;
|
||||
__rc_client_achievement_type_enum_t achievement_type;
|
||||
__rc_client_achievement_bucket_enum_t achievement_bucket;
|
||||
__rc_client_achievement_unlocked_enum_t achievement_unlocked;
|
||||
__rc_client_leaderboard_state_enum_t leaderboard_state;
|
||||
__rc_client_leaderboard_format_enum_t leaderboard_format;
|
||||
__rc_client_log_level_enum_t log_level;
|
||||
__rc_client_event_type_enum_t event_type;
|
||||
__rc_client_load_game_state_enum_t load_game_state;
|
||||
__rc_client_user_state_enum_t user_state;
|
||||
__rc_client_mastery_state_enum_t mastery_state;
|
||||
__rc_client_spectator_mode_enum_t spectator_mode;
|
||||
__rc_client_disconnect_enum_t disconnect;
|
||||
__rc_client_leaderboard_tracker_list_t leaderboard_tracker_list;
|
||||
__rc_client_subset_info_list_t subset_info_list;
|
||||
__rc_client_media_hash_list_t media_hash_list;
|
||||
__rc_client_subset_info_achievements_list_t subset_info_achievements_list;
|
||||
__rc_client_subset_info_leaderboards_list_t subset_info_leaderboards_list;
|
||||
__rc_client_scheduled_callback_list_t scheduled_callback_list;
|
||||
__rc_client_game_hash_list_t client_game_hash_list;
|
||||
} natvis;
|
||||
|
||||
memset(&natvis, 0, sizeof(natvis));
|
||||
(void)event;
|
||||
(void)client;
|
||||
|
||||
/* this code should never be executed. it just ensures these constants get defined for
|
||||
* the natvis VisualStudio extension as they're not used directly in the code. */
|
||||
natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD;
|
||||
natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE;
|
||||
natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION;
|
||||
natvis.achievement_type.value = RC_CLIENT_ACHIEVEMENT_TYPE_WIN;
|
||||
natvis.achievement_category.value = RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE;
|
||||
natvis.event_type.value = RC_CLIENT_EVENT_TYPE_NONE;
|
||||
}
|
||||
|
||||
/* ===== Construction/Destruction ===== */
|
||||
|
||||
static void rc_client_dummy_event_handler(const rc_client_event_t* event, rc_client_t* client)
|
||||
@@ -110,6 +174,7 @@ rc_client_t* rc_client_create(rc_client_read_memory_func_t read_memory_function,
|
||||
|
||||
client->callbacks.read_memory = read_memory_function;
|
||||
client->callbacks.server_call = server_call_function;
|
||||
client->callbacks.event_handler = rc_client_natvis_helper;
|
||||
client->callbacks.event_handler = rc_client_dummy_event_handler;
|
||||
rc_client_set_legacy_peek(client, RC_CLIENT_LEGACY_PEEK_AUTO);
|
||||
rc_client_set_get_time_millisecs_function(client, NULL);
|
||||
@@ -180,7 +245,7 @@ static void rc_client_log_message_va(const rc_client_t* client, const char* form
|
||||
if (client->callbacks.log_call) {
|
||||
char buffer[2048];
|
||||
|
||||
#ifdef __STDC_WANT_SECURE_LIB__
|
||||
#ifdef __STDC_SECURE_LIB__
|
||||
vsprintf_s(buffer, sizeof(buffer), format, args);
|
||||
#elif __STDC_VERSION__ >= 199901L /* vsnprintf requires c99 */
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
@@ -1071,27 +1136,23 @@ static void rc_client_validate_addresses(rc_client_game_info_t* game, rc_client_
|
||||
uint32_t total_count = 0;
|
||||
uint32_t invalid_count = 0;
|
||||
|
||||
rc_memref_t** last_memref = &game->runtime.memrefs;
|
||||
rc_memref_t* memref = game->runtime.memrefs;
|
||||
for (; memref; memref = memref->next) {
|
||||
if (!memref->value.is_indirect) {
|
||||
total_count++;
|
||||
rc_memref_list_t* memref_list = &game->runtime.memrefs->memrefs;
|
||||
for (; memref_list; memref_list = memref_list->next) {
|
||||
rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_end = memref + memref_list->count;
|
||||
total_count += memref_list->count;
|
||||
|
||||
for (; memref < memref_end; ++memref) {
|
||||
if (memref->address > max_address ||
|
||||
client->callbacks.read_memory(memref->address, buffer, 1, client) == 0) {
|
||||
/* invalid address, remove from chain so we don't have to evaluate it in the future.
|
||||
* it's still there, so anything referencing it will always fetch 0. */
|
||||
*last_memref = memref->next;
|
||||
client->callbacks.read_memory(memref->address, buffer, 1, client) == 0) {
|
||||
memref->value.type = RC_VALUE_TYPE_NONE;
|
||||
|
||||
rc_client_invalidate_memref_achievements(game, client, memref);
|
||||
rc_client_invalidate_memref_leaderboards(game, client, memref);
|
||||
|
||||
invalid_count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
last_memref = &memref->next;
|
||||
}
|
||||
|
||||
game->max_valid_address = max_address;
|
||||
@@ -1654,9 +1715,10 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
|
||||
rc_client_achievement_info_t* achievement;
|
||||
rc_client_achievement_info_t* scan;
|
||||
rc_buffer_t* buffer;
|
||||
rc_parse_state_t parse;
|
||||
rc_preparse_state_t preparse;
|
||||
const char* memaddr;
|
||||
size_t size;
|
||||
rc_trigger_t* trigger;
|
||||
int trigger_size;
|
||||
|
||||
subset->achievements = NULL;
|
||||
@@ -1686,11 +1748,11 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
|
||||
+ sizeof(rc_trigger_t) + sizeof(rc_condset_t) * 2 /* trigger container */
|
||||
+ sizeof(rc_condition_t) * 8 /* assume average trigger length of 8 conditions */
|
||||
+ sizeof(rc_client_achievement_info_t);
|
||||
rc_buffer_reserve(&load_state->game->buffer, size * num_achievements);
|
||||
buffer = &load_state->game->buffer;
|
||||
rc_buffer_reserve(buffer, size * num_achievements);
|
||||
|
||||
/* allocate the achievement array */
|
||||
size = sizeof(rc_client_achievement_info_t) * num_achievements;
|
||||
buffer = &load_state->game->buffer;
|
||||
achievement = achievements = rc_buffer_alloc(buffer, size);
|
||||
memset(achievements, 0, size);
|
||||
|
||||
@@ -1713,7 +1775,12 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
|
||||
memaddr = read->definition;
|
||||
rc_runtime_checksum(memaddr, achievement->md5);
|
||||
|
||||
trigger_size = rc_trigger_size(memaddr);
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
preparse.parse.existing_memrefs = load_state->game->runtime.memrefs;
|
||||
trigger = RC_ALLOC(rc_trigger_t, &preparse.parse);
|
||||
rc_parse_trigger_internal(trigger, &memaddr, &preparse.parse);
|
||||
|
||||
trigger_size = preparse.parse.offset;
|
||||
if (trigger_size < 0) {
|
||||
RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", trigger_size, read->id);
|
||||
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED;
|
||||
@@ -1721,23 +1788,22 @@ static void rc_client_copy_achievements(rc_client_load_state_t* load_state,
|
||||
}
|
||||
else {
|
||||
/* populate the item, using the communal memrefs pool */
|
||||
rc_init_parse_state(&parse, rc_buffer_reserve(buffer, trigger_size), NULL, 0);
|
||||
parse.first_memref = &load_state->game->runtime.memrefs;
|
||||
parse.variables = &load_state->game->runtime.variables;
|
||||
achievement->trigger = RC_ALLOC(rc_trigger_t, &parse);
|
||||
rc_parse_trigger_internal(achievement->trigger, &memaddr, &parse);
|
||||
rc_reset_parse_state(&preparse.parse, rc_buffer_reserve(buffer, trigger_size), NULL, 0);
|
||||
rc_preparse_reserve_memrefs(&preparse, load_state->game->runtime.memrefs);
|
||||
achievement->trigger = RC_ALLOC(rc_trigger_t, &preparse.parse);
|
||||
memaddr = read->definition;
|
||||
rc_parse_trigger_internal(achievement->trigger, &memaddr, &preparse.parse);
|
||||
|
||||
if (parse.offset < 0) {
|
||||
RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", parse.offset, read->id);
|
||||
if (preparse.parse.offset < 0) {
|
||||
RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing achievement %u", preparse.parse.offset, read->id);
|
||||
achievement->public_.state = RC_CLIENT_ACHIEVEMENT_STATE_DISABLED;
|
||||
achievement->public_.bucket = RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED;
|
||||
}
|
||||
else {
|
||||
rc_buffer_consume(buffer, parse.buffer, (uint8_t*)parse.buffer + parse.offset);
|
||||
achievement->trigger->memrefs = NULL; /* memrefs managed by runtime */
|
||||
rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
|
||||
}
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
}
|
||||
|
||||
achievement->created_time = read->created;
|
||||
@@ -1801,10 +1867,11 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
|
||||
rc_client_leaderboard_info_t* leaderboards;
|
||||
rc_client_leaderboard_info_t* leaderboard;
|
||||
rc_buffer_t* buffer;
|
||||
rc_parse_state_t parse;
|
||||
rc_preparse_state_t preparse;
|
||||
const char* memaddr;
|
||||
const char* ptr;
|
||||
size_t size;
|
||||
rc_lboard_t* lboard;
|
||||
int lboard_size;
|
||||
|
||||
subset->leaderboards = NULL;
|
||||
@@ -1854,29 +1921,32 @@ static void rc_client_copy_leaderboards(rc_client_load_state_t* load_state,
|
||||
leaderboard->value_djb2 = hash;
|
||||
}
|
||||
|
||||
lboard_size = rc_lboard_size(memaddr);
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
preparse.parse.existing_memrefs = load_state->game->runtime.memrefs;
|
||||
lboard = RC_ALLOC(rc_lboard_t, &preparse.parse);
|
||||
rc_parse_lboard_internal(lboard, memaddr, &preparse.parse);
|
||||
|
||||
lboard_size = preparse.parse.offset;
|
||||
if (lboard_size < 0) {
|
||||
RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", lboard_size, read->id);
|
||||
leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED;
|
||||
}
|
||||
else {
|
||||
/* populate the item, using the communal memrefs pool */
|
||||
rc_init_parse_state(&parse, rc_buffer_reserve(buffer, lboard_size), NULL, 0);
|
||||
parse.first_memref = &load_state->game->runtime.memrefs;
|
||||
parse.variables = &load_state->game->runtime.variables;
|
||||
leaderboard->lboard = RC_ALLOC(rc_lboard_t, &parse);
|
||||
rc_parse_lboard_internal(leaderboard->lboard, memaddr, &parse);
|
||||
rc_reset_parse_state(&preparse.parse, rc_buffer_reserve(buffer, lboard_size), NULL, 0);
|
||||
rc_preparse_reserve_memrefs(&preparse, load_state->game->runtime.memrefs);
|
||||
leaderboard->lboard = RC_ALLOC(rc_lboard_t, &preparse.parse);
|
||||
rc_parse_lboard_internal(leaderboard->lboard, memaddr, &preparse.parse);
|
||||
|
||||
if (parse.offset < 0) {
|
||||
RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", parse.offset, read->id);
|
||||
if (preparse.parse.offset < 0) {
|
||||
RC_CLIENT_LOG_WARN_FORMATTED(load_state->client, "Parse error %d processing leaderboard %u", preparse.parse.offset, read->id);
|
||||
leaderboard->public_.state = RC_CLIENT_LEADERBOARD_STATE_DISABLED;
|
||||
}
|
||||
else {
|
||||
rc_buffer_consume(buffer, parse.buffer, (uint8_t*)parse.buffer + parse.offset);
|
||||
leaderboard->lboard->memrefs = NULL; /* memrefs managed by runtime */
|
||||
rc_buffer_consume(buffer, preparse.parse.buffer, (uint8_t*)preparse.parse.buffer + preparse.parse.offset);
|
||||
}
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
}
|
||||
|
||||
++leaderboard;
|
||||
@@ -4801,22 +4871,11 @@ void rc_client_set_read_memory_function(rc_client_t* client, rc_client_read_memo
|
||||
|
||||
static void rc_client_invalidate_processing_memref(rc_client_t* client)
|
||||
{
|
||||
rc_memref_t** next_memref = &client->game->runtime.memrefs;
|
||||
rc_memref_t* memref;
|
||||
|
||||
/* if processing_memref is not set, this occurred following a pointer chain. ignore it. */
|
||||
if (!client->state.processing_memref)
|
||||
return;
|
||||
|
||||
/* invalid memref. remove from chain so we don't have to evaluate it in the future.
|
||||
* it's still there, so anything referencing it will always fetch the current value. */
|
||||
while ((memref = *next_memref) != NULL) {
|
||||
if (memref == client->state.processing_memref) {
|
||||
*next_memref = memref->next;
|
||||
break;
|
||||
}
|
||||
next_memref = &memref->next;
|
||||
}
|
||||
client->state.processing_memref->value.type = RC_VALUE_TYPE_NONE;
|
||||
|
||||
rc_client_invalidate_memref_achievements(client->game, client, client->state.processing_memref);
|
||||
rc_client_invalidate_memref_leaderboards(client->game, client, client->state.processing_memref);
|
||||
@@ -4924,31 +4983,57 @@ int rc_client_is_processing_required(rc_client_t* client)
|
||||
return (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence);
|
||||
}
|
||||
|
||||
static void rc_client_update_memref_values(rc_client_t* client)
|
||||
{
|
||||
rc_memref_t* memref = client->game->runtime.memrefs;
|
||||
uint32_t value;
|
||||
static void rc_client_update_memref_values(rc_client_t* client) {
|
||||
rc_memrefs_t* memrefs = client->game->runtime.memrefs;
|
||||
rc_memref_list_t* memref_list;
|
||||
rc_modified_memref_list_t* modified_memref_list;
|
||||
int invalidated_memref = 0;
|
||||
|
||||
for (; memref; memref = memref->next) {
|
||||
if (memref->value.is_indirect)
|
||||
continue;
|
||||
memref_list = &memrefs->memrefs;
|
||||
do {
|
||||
rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_stop = memref + memref_list->count;
|
||||
uint32_t value;
|
||||
|
||||
client->state.processing_memref = memref;
|
||||
for (; memref < memref_stop; ++memref) {
|
||||
if (memref->value.type == RC_VALUE_TYPE_NONE)
|
||||
continue;
|
||||
|
||||
value = rc_peek_value(memref->address, memref->value.size, client->state.legacy_peek, client);
|
||||
/* if processing_memref is set, and the memory read fails, all dependent achievements will be disabled */
|
||||
client->state.processing_memref = memref;
|
||||
|
||||
if (client->state.processing_memref) {
|
||||
rc_update_memref_value(&memref->value, value);
|
||||
value = rc_peek_value(memref->address, memref->value.size, client->state.legacy_peek, client);
|
||||
|
||||
if (client->state.processing_memref) {
|
||||
rc_update_memref_value(&memref->value, value);
|
||||
}
|
||||
else {
|
||||
/* if the peek function cleared the processing_memref, the memref was invalidated */
|
||||
invalidated_memref = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* if the peek function cleared the processing_memref, the memref was invalidated */
|
||||
invalidated_memref = 1;
|
||||
}
|
||||
}
|
||||
|
||||
memref_list = memref_list->next;
|
||||
} while (memref_list);
|
||||
|
||||
client->state.processing_memref = NULL;
|
||||
|
||||
modified_memref_list = &memrefs->modified_memrefs;
|
||||
if (modified_memref_list->count) {
|
||||
do {
|
||||
rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
||||
const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count;
|
||||
|
||||
for (; modified_memref < modified_memref_stop; ++modified_memref)
|
||||
rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, client->state.legacy_peek, client));
|
||||
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
} while (modified_memref_list);
|
||||
}
|
||||
|
||||
if (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence)
|
||||
rc_update_values(client->game->runtime.richpresence->richpresence->values, client->state.legacy_peek, client, NULL);
|
||||
|
||||
if (invalidated_memref)
|
||||
rc_client_update_active_achievements(client->game);
|
||||
}
|
||||
@@ -5362,7 +5447,6 @@ void rc_client_do_frame(rc_client_t* client)
|
||||
rc_client_reset_pending_events(client);
|
||||
|
||||
rc_client_update_memref_values(client);
|
||||
rc_update_variables(client->game->runtime.variables, client->state.legacy_peek, client, NULL);
|
||||
|
||||
client->game->progress_tracker.progress = 0.0;
|
||||
for (subset = client->game->subsets; subset; subset = subset->next) {
|
||||
@@ -5534,9 +5618,8 @@ static void rc_client_reset_richpresence(rc_client_t* client)
|
||||
|
||||
static void rc_client_reset_variables(rc_client_t* client)
|
||||
{
|
||||
rc_value_t* variable = client->game->runtime.variables;
|
||||
for (; variable; variable = variable->next)
|
||||
rc_reset_value(variable);
|
||||
if (client->game->runtime.richpresence && client->game->runtime.richpresence->richpresence)
|
||||
rc_reset_values(client->game->runtime.richpresence->richpresence->values);
|
||||
}
|
||||
|
||||
static void rc_client_reset_all(rc_client_t* client)
|
||||
|
||||
@@ -6,6 +6,24 @@
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION
|
||||
|
||||
/* ===== natvis extensions ===== */
|
||||
|
||||
typedef struct __rc_client_raintegration_event_enum_t { uint8_t value; } __rc_client_raintegration_event_enum_t;
|
||||
static void rc_client_raintegration_natvis_helper(void)
|
||||
{
|
||||
struct natvis_extensions {
|
||||
__rc_client_raintegration_event_enum_t raintegration_event_type;
|
||||
} natvis;
|
||||
|
||||
natvis.raintegration_event_type.value = RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE;
|
||||
natvis.raintegration_event_type.value = RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED;
|
||||
natvis.raintegration_event_type.value = RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED;
|
||||
natvis.raintegration_event_type.value = RC_CLIENT_RAINTEGRATION_EVENT_PAUSE;
|
||||
natvis.raintegration_event_type.value = RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED;
|
||||
}
|
||||
|
||||
/* ============================= */
|
||||
|
||||
static void rc_client_raintegration_load_dll(rc_client_t* client,
|
||||
const wchar_t* search_directory, rc_client_callback_t callback, void* callback_userdata)
|
||||
{
|
||||
@@ -89,6 +107,9 @@ static void rc_client_raintegration_load_dll(rc_client_t* client,
|
||||
FreeLibrary(hDLL);
|
||||
|
||||
callback(RC_ABORTED, "One or more required exports was not found in RA_Integration.dll", client, callback_userdata);
|
||||
|
||||
/* dummy reference to natvis helper to ensure extensions get compiled in. */
|
||||
raintegration->shutdown = rc_client_raintegration_natvis_helper;
|
||||
}
|
||||
else {
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
|
||||
394
dep/rcheevos/src/rc_client_types.natvis
Normal file
394
dep/rcheevos/src/rc_client_types.natvis
Normal file
@@ -0,0 +1,394 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<!-- https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022 -->
|
||||
<!-- https://learn.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2022 -->
|
||||
<Type Name="rc_client_user_t">
|
||||
<DisplayString>{{display_name={display_name,s} score={score}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_game_t">
|
||||
<DisplayString>{{title={title,s} id={id}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_subset_t">
|
||||
<DisplayString>{{title={title,s} id={id}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_achievement_state_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE">{RC_CLIENT_ACHIEVEMENT_STATE_INACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE">{RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED">{RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_STATE_DISABLED">{RC_CLIENT_ACHIEVEMENT_STATE_DISABLED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_achievement_category_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE">{RC_CLIENT_ACHIEVEMENT_CATEGORY_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE">{RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL">{RC_CLIENT_ACHIEVEMENT_CATEGORY_UNOFFICIAL}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL">{RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_achievement_type_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD">{RC_CLIENT_ACHIEVEMENT_TYPE_STANDARD}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE">{RC_CLIENT_ACHIEVEMENT_TYPE_MISSABLE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION">{RC_CLIENT_ACHIEVEMENT_TYPE_PROGRESSION}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_TYPE_WIN">{RC_CLIENT_ACHIEVEMENT_TYPE_WIN}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_achievement_bucket_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNKNOWN}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED">{RC_CLIENT_ACHIEVEMENT_BUCKET_LOCKED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNLOCKED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNOFFICIAL}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED">{RC_CLIENT_ACHIEVEMENT_BUCKET_RECENTLY_UNLOCKED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE">{RC_CLIENT_ACHIEVEMENT_BUCKET_ACTIVE_CHALLENGE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNSUPPORTED">{RC_CLIENT_ACHIEVEMENT_BUCKET_ALMOST_THERE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED">{RC_CLIENT_ACHIEVEMENT_BUCKET_UNSYNCED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_achievement_unlocked_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH">{RC_CLIENT_ACHIEVEMENT_UNLOCKED_BOTH}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_achievement_t">
|
||||
<DisplayString>{{title={title,s} id={id}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="title">title</Item>
|
||||
<Item Name="description">description</Item>
|
||||
<Item Name="points">points</Item>
|
||||
<Item Name="id">id</Item>
|
||||
<Item Name="state">*((__rc_client_achievement_state_enum_t*)&state)</Item>
|
||||
<Item Name="type">*((__rc_client_achievement_type_enum_t*)&state)</Item>
|
||||
<Item Name="category">*((__rc_client_achievement_category_enum_t*)&category)</Item>
|
||||
<Item Name="bucket">*((__rc_client_achievement_state_enum_t*)&bucket)</Item>
|
||||
<Item Name="unlocked">*((__rc_client_achievement_unlocked_enum_t*)&unlocked)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_achievement_bucket_t">
|
||||
<DisplayString>{{label={label,s} count={num_achievements}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>num_achievements</Size>
|
||||
<ValueNode>achievements[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_achievement_list_t">
|
||||
<DisplayString>{{count={num_buckets}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>num_buckets</Size>
|
||||
<ValueNode>buckets[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_leaderboard_state_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_INACTIVE">{RC_CLIENT_LEADERBOARD_STATE_INACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_ACTIVE">{RC_CLIENT_LEADERBOARD_STATE_ACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_TRACKING">{RC_CLIENT_LEADERBOARD_STATE_TRACKING}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_STATE_DISABLED">{RC_CLIENT_LEADERBOARD_STATE_DISABLED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_leaderboard_format_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_FORMAT_TIME">{RC_CLIENT_LEADERBOARD_FORMAT_TIME}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_FORMAT_SCORE">{RC_CLIENT_LEADERBOARD_FORMAT_SCORE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LEADERBOARD_FORMAT_VALUE">{RC_CLIENT_LEADERBOARD_FORMAT_VALUE}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_leaderboard_t">
|
||||
<DisplayString>{{title={title,s} id={id}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="title">title</Item>
|
||||
<Item Name="description">description</Item>
|
||||
<Item Name="tracker_value">tracker_value</Item>
|
||||
<Item Name="id">id</Item>
|
||||
<Item Name="state">*((__rc_client_leaderboard_state_enum_t*)&state)</Item>
|
||||
<Item Name="format">*((__rc_client_leaderboard_format_enum_t*)&format)</Item>
|
||||
<Item Name="lower_is_better">*((__rc_bool_enum_t*)&lower_is_better)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_leaderboard_bucket_t">
|
||||
<DisplayString>{{label={label,s} count={num_leaderboards}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>num_leaderboards</Size>
|
||||
<ValueNode>leaderboards[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_leaderboard_list_t">
|
||||
<DisplayString>{{count={num_buckets}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>num_buckets</Size>
|
||||
<ValueNode>buckets[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_leaderboard_scoreboard_entry_t">
|
||||
<DisplayString>{{rank={rank} score={score,s} username={username}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_leaderboard_scoreboard_t">
|
||||
<DisplayString>{{leaderboard_id={leaderboard_id} num_entries={num_entries}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="leaderboard_id">leaderboard_id</Item>
|
||||
<Item Name="submitted_score">submitted_score</Item>
|
||||
<Item Name="best_score">best_score</Item>
|
||||
<Item Name="new_rank">new_rank</Item>
|
||||
<Item Name="num_entries">num_entries</Item>
|
||||
<IndexListItems>
|
||||
<Size>num_top_entries</Size>
|
||||
<ValueNode>top_entries[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_event_type_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_TYPE_NONE">{RC_CLIENT_EVENT_TYPE_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED">{RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_STARTED">{RC_CLIENT_EVENT_LEADERBOARD_STARTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_FAILED">{RC_CLIENT_EVENT_LEADERBOARD_FAILED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED">{RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW">{RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE">{RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW">{RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE">{RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE">{RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW">{RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE">{RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE">{RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD">{RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_RESET">{RC_CLIENT_EVENT_RESET}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_GAME_COMPLETED">{RC_CLIENT_EVENT_GAME_COMPLETED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_SERVER_ERROR">{RC_CLIENT_EVENT_SERVER_ERROR}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_DISCONNECTED">{RC_CLIENT_EVENT_DISCONNECTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_EVENT_RECONNECTED">{RC_CLIENT_EVENT_RECONNECTED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_event_t">
|
||||
<DisplayString>{{type={*((__rc_client_event_type_enum_t*)&type)}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="type">*((__rc_client_event_type_enum_t*)&type)</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_TRIGGERED" Name="achievement">*achievement</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_STARTED" Name="leaderboard">*leaderboard</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_FAILED" Name="leaderboard">*leaderboard</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_SUBMITTED" Name="leaderboard">*leaderboard</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_SHOW" Name="achievement">*achievement</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_CHALLENGE_INDICATOR_HIDE" Name="achievement">*achievement</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_SHOW" Name="achievement">*achievement</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_HIDE" Name="achievement">*achievement</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_ACHIEVEMENT_PROGRESS_INDICATOR_UPDATE" Name="achievement">*achievement</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_SHOW" Name="leaderboard_tracker">*leaderboard_tracker</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_HIDE" Name="leaderboard_tracker">*leaderboard_tracker</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_TRACKER_UPDATE" Name="leaderboard_tracker">*leaderboard_tracker</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD" Name="leaderboard_scoreboard">*leaderboard_scoreboard</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_LEADERBOARD_SCOREBOARD" Name="leaderboard">*leaderboard</Item>
|
||||
<Item Condition="type==RC_CLIENT_EVENT_SERVER_ERROR" Name="server_error">*server_error</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_subset_info_achievements_list_t">
|
||||
<DisplayString>{{count={info.public_.num_achievements}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>info.public_.num_achievements</Size>
|
||||
<ValueNode>info.achievements[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_subset_info_leaderboards_list_t">
|
||||
<DisplayString>{{count={info.public_.num_leaderboards}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>info.public_.num_leaderboards</Size>
|
||||
<ValueNode>info.leaderboards[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_mastery_state_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_MASTERY_STATE_NONE">{RC_CLIENT_MASTERY_STATE_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_MASTERY_STATE_PENDING">{RC_CLIENT_MASTERY_STATE_PENDING}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_MASTERY_STATE_SHOWN">{RC_CLIENT_MASTERY_STATE_SHOWN}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_subset_info_t">
|
||||
<DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="public_">public_</Item>
|
||||
<Item Name="active">*((__rc_bool_enum_t*)&active)</Item>
|
||||
<Item Name="mastery">*((__rc_client_mastery_state_enum_t*)&mastery)</Item>
|
||||
<Item Name="achievements">*((__rc_client_subset_info_achievements_list_t*)this)</Item>
|
||||
<Item Name="leaderboards">*((__rc_client_subset_info_leaderboards_list_t*)this)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_leaderboard_tracker_list_t">
|
||||
<DisplayString Condition="first==0">{{NULL}}</DisplayString>
|
||||
<DisplayString>{(void**)&first,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_subset_info_list_t">
|
||||
<DisplayString Condition="first==0">{{NULL}}</DisplayString>
|
||||
<DisplayString>{(void**)&first,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_media_hash_list_t">
|
||||
<DisplayString Condition="first==0">{{NULL}}</DisplayString>
|
||||
<DisplayString>{(void**)&first,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_achievement_info_t">
|
||||
<DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_leaderboard_info_t">
|
||||
<DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_game_info_t">
|
||||
<DisplayString>{{title={public_.title,s} id={public_.id}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="public_">public_</Item>
|
||||
<Item Name="subsets">*((__rc_client_subset_info_list_t*)&subsets)</Item>
|
||||
<Item Name="media_hash">*((__rc_client_media_hash_list_t*)&media_hash)</Item>
|
||||
<Item Name="leaderboard_trackers">*((__rc_client_leaderboard_tracker_list_t*)&leaderboard_trackers)</Item>
|
||||
<Item Name="progress_tracker">progress_tracker</Item>
|
||||
<Item Name="runtime">runtime</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_game_hash_t">
|
||||
<DisplayString>{{hash={hash,s} game_id={game_id}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_game_hash_list_t">
|
||||
<DisplayString>{client.hashes}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>client.hashes</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>*this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_load_game_state_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_NONE">{RC_CLIENT_LOAD_GAME_STATE_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME">{RC_CLIENT_LOAD_GAME_STATE_IDENTIFYING_GAME}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN">{RC_CLIENT_LOAD_GAME_STATE_AWAIT_LOGIN}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_FETCHING_GAME_DATA">{RC_CLIENT_LOAD_GAME_STATE_FETCHING_GAME_DATA}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION">{RC_CLIENT_LOAD_GAME_STATE_STARTING_SESSION}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_DONE">{RC_CLIENT_LOAD_GAME_STATE_DONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOAD_GAME_STATE_ABORTED">{RC_CLIENT_LOAD_GAME_STATE_ABORTED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_load_state_t">
|
||||
<Expand>
|
||||
<Item Name="progress">*((__rc_client_load_game_state_enum_t*)&progress)</Item>
|
||||
<Item Name="game">*game</Item>
|
||||
<Item Name="subset">subset</Item>
|
||||
<Item Name="hash">*hash</Item>
|
||||
<Item Name="pending_media">pending_media</Item>
|
||||
<Item Name="start_session_response">start_session_response</Item>
|
||||
<Item Name="outstanding_requests">(int)outstanding_requests</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_scheduled_callback_data_t">
|
||||
<DisplayString>{{when={when} callback={callback,na}}}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_scheduled_callback_list_t">
|
||||
<DisplayString>{state.scheduled_callbacks}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>state.scheduled_callbacks</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>*this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_log_level_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_NONE">{RC_CLIENT_LOG_LEVEL_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_ERROR">{RC_CLIENT_LOG_LEVEL_ERROR}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_WARN">{RC_CLIENT_LOG_LEVEL_WARN}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_INFO">{RC_CLIENT_LOG_LEVEL_INFO}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_LOG_LEVEL_VERBOSE">{RC_CLIENT_LOG_LEVEL_VERBOSE}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_user_state_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_USER_STATE_NONE">{RC_CLIENT_USER_STATE_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_USER_STATE_LOGIN_REQUESTED">{RC_CLIENT_USER_STATE_LOGIN_REQUESTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_USER_STATE_LOGGED_IN">{RC_CLIENT_USER_STATE_LOGGED_IN}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_spectator_mode_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_SPECTATOR_MODE_OFF">{RC_CLIENT_SPECTATOR_MODE_OFF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_SPECTATOR_MODE_ON">{RC_CLIENT_SPECTATOR_MODE_ON}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_SPECTATOR_MODE_LOCKED">{RC_CLIENT_SPECTATOR_MODE_LOCKED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_client_disconnect_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_DISCONNECT_HIDDEN">{RC_CLIENT_DISCONNECT_HIDDEN}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_DISCONNECT_VISIBLE">{RC_CLIENT_DISCONNECT_VISIBLE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_DISCONNECT_SHOW_PENDING">{RC_CLIENT_DISCONNECT_SHOW_PENDING}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_DISCONNECT_HIDE_PENDING">{RC_CLIENT_DISCONNECT_HIDE_PENDING}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_DISCONNECT_VISIBLE|RC_CLIENT_DISCONNECT_HIDE_PENDING">{RC_CLIENT_DISCONNECT_VISIBLE|RC_CLIENT_DISCONNECT_HIDE_PENDING}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_state_t">
|
||||
<Expand>
|
||||
<Item Name="hardcore">*((__rc_bool_enum_t*)&hardcore)</Item>
|
||||
<Item Name="unofficial_enabled">*((__rc_bool_enum_t*)&unofficial_enabled)</Item>
|
||||
<Item Name="encore_mode">*((__rc_bool_enum_t*)&encore_mode)</Item>
|
||||
<Item Name="spectator_mode">*((__rc_client_spectator_mode_enum_t*)&spectator_mode)</Item>
|
||||
<Item Name="disconnect">*((__rc_client_disconnect_enum_t*)&disconnect)</Item>
|
||||
<Item Name="log_level">*((__rc_client_log_level_enum_t*)&log_level)</Item>
|
||||
<Item Name="user">*((__rc_client_user_state_enum_t*)&user)</Item>
|
||||
<Item Name="scheduled_callbacks">*((__rc_client_scheduled_callback_list_t*)this)</Item>
|
||||
<Item Name="load">load</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_t">
|
||||
<Expand>
|
||||
<Item Name="game">game</Item>
|
||||
<Item Name="hashes">*((__rc_client_game_hash_list_t*)&hashes)</Item>
|
||||
<Item Name="user">user</Item>
|
||||
<Item Name="callbacks">callbacks</Item>
|
||||
<Item Name="state">state</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_client_raintegration_menu_t">
|
||||
<DisplayString>{{count={num_items}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>num_items</Size>
|
||||
<ValueNode>items[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_client_raintegration_event_enum_t">
|
||||
<DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE">{RC_CLIENT_RAINTEGRATION_EVENT_TYPE_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED">{RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED">{RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_PAUSE">{RC_CLIENT_RAINTEGRATION_EVENT_PAUSE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED">{RC_CLIENT_RAINTEGRATION_EVENT_MENU_CHANGED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_client_raintegration_event_t">
|
||||
<DisplayString>{{type={*((__rc_client_raintegration_event_enum_t*)&type)}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="type">*((__rc_client_raintegration_event_enum_t*)&type)</Item>
|
||||
<Item Condition="type==RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED" Name="menu_item">menu_item</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
||||
@@ -1,5 +1,15 @@
|
||||
#if !defined(RC_NO_THREADS) && !defined(_WIN32) && !defined(GEKKO) && !defined(_3DS) && (!defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0) < 500)
|
||||
/* We'll want to use pthread_mutexattr_settype/PTHREAD_MUTEX_RECURSIVE, but glibc only conditionally exposes pthread_mutexattr_settype and PTHREAD_MUTEX_RECURSIVE depending on feature flags
|
||||
* Defining _XOPEN_SOURCE must be done at the top of the source file, before including any headers
|
||||
* pthread_mutexattr_settype/PTHREAD_MUTEX_RECURSIVE are specified the Single UNIX Specification (Version 2, 1997), along with POSIX later on (IEEE Standard 1003.1-2008), so should cover practically any pthread implementation
|
||||
*/
|
||||
#undef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
|
||||
#include "rc_compat.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -58,7 +68,7 @@ int rc_snprintf(char* buffer, size_t size, const char* format, ...)
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
#ifdef __STDC_WANT_SECURE_LIB__
|
||||
#ifdef __STDC_SECURE_LIB__
|
||||
result = vsprintf_s(buffer, size, format, args);
|
||||
#else
|
||||
/* assume buffer is large enough and ignore size */
|
||||
@@ -73,7 +83,7 @@ int rc_snprintf(char* buffer, size_t size, const char* format, ...)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __STDC_WANT_SECURE_LIB__
|
||||
#ifndef __STDC_SECURE_LIB__
|
||||
|
||||
struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer)
|
||||
{
|
||||
@@ -88,61 +98,138 @@ struct tm* rc_gmtime_s(struct tm* buf, const time_t* timer)
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
/* https://gist.github.com/roxlu/1c1af99f92bafff9d8d9 */
|
||||
/* https://learn.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c */
|
||||
/* implementation largely taken from https://github.com/libsdl-org/SDL/blob/0fc3574/src/thread/windows/SDL_sysmutex.c */
|
||||
|
||||
#if defined(WINVER) && WINVER >= 0x0600
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
void rc_mutex_init(rc_mutex_t* mutex)
|
||||
{
|
||||
/* default security, not owned by calling thread, unnamed */
|
||||
mutex->handle = CreateMutex(NULL, FALSE, NULL);
|
||||
InitializeSRWLock(&mutex->srw_lock);
|
||||
/* https://learn.microsoft.com/en-us/windows/win32/procthread/thread-handles-and-identifiers */
|
||||
/* thread ids are never 0 */
|
||||
mutex->owner = 0;
|
||||
mutex->count = 0;
|
||||
}
|
||||
|
||||
void rc_mutex_destroy(rc_mutex_t* mutex)
|
||||
{
|
||||
CloseHandle(mutex->handle);
|
||||
/* Nothing to do here */
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
void rc_mutex_lock(rc_mutex_t* mutex)
|
||||
{
|
||||
WaitForSingleObject(mutex->handle, 0xFFFFFFFF);
|
||||
DWORD current_thread = GetCurrentThreadId();
|
||||
if (mutex->owner == current_thread) {
|
||||
++mutex->count;
|
||||
assert(mutex->count > 0);
|
||||
}
|
||||
else {
|
||||
AcquireSRWLockExclusive(&mutex->srw_lock);
|
||||
assert(mutex->owner == 0 && mutex->count == 0);
|
||||
mutex->owner = current_thread;
|
||||
mutex->count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void rc_mutex_unlock(rc_mutex_t* mutex)
|
||||
{
|
||||
ReleaseMutex(mutex->handle);
|
||||
if (mutex->owner == GetCurrentThreadId()) {
|
||||
assert(mutex->count > 0);
|
||||
if (--mutex->count == 0) {
|
||||
mutex->owner = 0;
|
||||
ReleaseSRWLockExclusive(&mutex->srw_lock);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(!"Tried to unlock unowned mutex");
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void rc_mutex_init(rc_mutex_t* mutex)
|
||||
{
|
||||
InitializeCriticalSection(&mutex->critical_section);
|
||||
}
|
||||
|
||||
void rc_mutex_destroy(rc_mutex_t* mutex)
|
||||
{
|
||||
DeleteCriticalSection(&mutex->critical_section);
|
||||
}
|
||||
|
||||
void rc_mutex_lock(rc_mutex_t* mutex)
|
||||
{
|
||||
EnterCriticalSection(&mutex->critical_section);
|
||||
}
|
||||
|
||||
void rc_mutex_unlock(rc_mutex_t* mutex)
|
||||
{
|
||||
LeaveCriticalSection(&mutex->critical_section);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(GEKKO)
|
||||
|
||||
/* https://github.com/libretro/RetroArch/pull/16116 */
|
||||
|
||||
void rc_mutex_init(rc_mutex_t* mutex)
|
||||
{
|
||||
LWP_MutexInit(mutex, NULL);
|
||||
/* LWP_MutexInit has the handle passed by reference */
|
||||
/* Other LWP_Mutex* calls have the handle passed by value */
|
||||
LWP_MutexInit(&mutex->handle, 1);
|
||||
}
|
||||
|
||||
void rc_mutex_destroy(rc_mutex_t* mutex)
|
||||
{
|
||||
LWP_MutexDestroy(mutex);
|
||||
LWP_MutexDestroy(mutex->handle);
|
||||
}
|
||||
|
||||
void rc_mutex_lock(rc_mutex_t* mutex)
|
||||
{
|
||||
LWP_MutexLock(mutex);
|
||||
LWP_MutexLock(mutex->handle);
|
||||
}
|
||||
|
||||
void rc_mutex_unlock(rc_mutex_t* mutex)
|
||||
{
|
||||
LWP_MutexUnlock(mutex);
|
||||
LWP_MutexUnlock(mutex->handle);
|
||||
}
|
||||
|
||||
#elif defined(_3DS)
|
||||
|
||||
void rc_mutex_init(rc_mutex_t* mutex)
|
||||
{
|
||||
RecursiveLock_Init(mutex);
|
||||
}
|
||||
|
||||
void rc_mutex_destroy(rc_mutex_t* mutex)
|
||||
{
|
||||
/* Nothing to do here */
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
void rc_mutex_lock(rc_mutex_t* mutex)
|
||||
{
|
||||
RecursiveLock_Lock(mutex);
|
||||
}
|
||||
|
||||
void rc_mutex_unlock(rc_mutex_t* mutex)
|
||||
{
|
||||
RecursiveLock_Unlock(mutex);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void rc_mutex_init(rc_mutex_t* mutex)
|
||||
{
|
||||
pthread_mutex_init(mutex, NULL);
|
||||
/* Define the mutex as recursive, for consistent semantics against other rc_mutex_t implementations */
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
void rc_mutex_destroy(rc_mutex_t* mutex)
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#ifndef RC_COMPAT_H
|
||||
#define RC_COMPAT_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "rc_export.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -58,7 +65,7 @@ RC_BEGIN_C_DECLS
|
||||
|
||||
#endif /* __STDC_VERSION__ < 199901L */
|
||||
|
||||
#ifndef __STDC_WANT_SECURE_LIB__
|
||||
#ifndef __STDC_SECURE_LIB__
|
||||
/* _CRT_SECURE_NO_WARNINGS redefinitions */
|
||||
#define strcpy_s(dest, sz, src) strcpy(dest, src)
|
||||
#define sscanf_s sscanf
|
||||
@@ -77,10 +84,27 @@ RC_BEGIN_C_DECLS
|
||||
#define rc_mutex_lock(mutex)
|
||||
#define rc_mutex_unlock(mutex)
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32)
|
||||
typedef struct rc_mutex_t {
|
||||
#if defined(WINVER) && WINVER >= 0x0600
|
||||
/* Windows Vista and later can use a slim reader/writer (SRW) lock */
|
||||
SRWLOCK srw_lock;
|
||||
/* Current thread owner needs to be tracked (for recursive mutex usage) */
|
||||
DWORD owner;
|
||||
DWORD count;
|
||||
#else
|
||||
/* Pre-Vista must use a critical section */
|
||||
CRITICAL_SECTION critical_section;
|
||||
#endif
|
||||
} rc_mutex_t;
|
||||
#elif defined(GEKKO)
|
||||
#include <ogcsys.h>
|
||||
typedef struct rc_mutex_t {
|
||||
void* handle; /* HANDLE is defined as "void*" */
|
||||
mutex_t handle;
|
||||
} rc_mutex_t;
|
||||
#elif defined(_3DS)
|
||||
#include <3ds/synchronization.h>
|
||||
typedef RecursiveLock rc_mutex_t;
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t rc_mutex_t;
|
||||
|
||||
@@ -124,7 +124,7 @@ static const rc_disallowed_setting_t _rc_disallowed_neocd_settings[] = {
|
||||
};
|
||||
|
||||
static const rc_disallowed_setting_t _rc_disallowed_pcsx_rearmed_settings[] = {
|
||||
{ "pcsx_rearmed_psxclock", "<55" },
|
||||
{ "pcsx_rearmed_psxclock", ",!auto,<55" },
|
||||
{ "pcsx_rearmed_region", "pal" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@@ -202,14 +202,14 @@ static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static int rc_libretro_string_equal_nocase_wildcard(const char* test, const char* value) {
|
||||
static int rc_libretro_string_equal_nocase_wildcard(const char* test, const char* match) {
|
||||
char c1, c2;
|
||||
while ((c1 = *test++)) {
|
||||
if (tolower(c1) != tolower(c2 = *value++) && c2 != '?')
|
||||
if (tolower(c1) != tolower(c2 = *match++) && c2 != '?')
|
||||
return (c2 == '*');
|
||||
}
|
||||
|
||||
return (*value == '\0');
|
||||
return (*match == '\0');
|
||||
}
|
||||
|
||||
static int rc_libretro_numeric_less_than(const char* test, const char* value) {
|
||||
@@ -218,7 +218,50 @@ static int rc_libretro_numeric_less_than(const char* test, const char* value) {
|
||||
return (test_num < value_num);
|
||||
}
|
||||
|
||||
static int rc_libretro_match_token(const char* val, const char* token, size_t size, int* result) {
|
||||
if (*token == '!') {
|
||||
/* !X => if X is a match, it's explicitly allowed. match with result = false */
|
||||
if (rc_libretro_match_token(val, token + 1, size - 1, result)) {
|
||||
*result = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*token == '<') {
|
||||
/* if val < token, match with result = true */
|
||||
char buffer[128];
|
||||
memcpy(buffer, token + 1, size - 1);
|
||||
buffer[size - 1] = '\0';
|
||||
if (rc_libretro_numeric_less_than(val, buffer)) {
|
||||
*result = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (memcmp(token, val, size) == 0 && val[size] == 0) {
|
||||
/* exact match, match with result = true */
|
||||
*result = 1;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
/* check for case insensitive match */
|
||||
char buffer[128];
|
||||
memcpy(buffer, token, size);
|
||||
buffer[size] = '\0';
|
||||
if (rc_libretro_string_equal_nocase_wildcard(val, buffer)) {
|
||||
/* case insensitive match, match with result = true */
|
||||
*result = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* no match */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rc_libretro_match_value(const char* val, const char* match) {
|
||||
int result = 0;
|
||||
|
||||
/* if value starts with a comma, it's a CSV list of potential matches */
|
||||
if (*match == ',') {
|
||||
do {
|
||||
@@ -229,33 +272,23 @@ static int rc_libretro_match_value(const char* val, const char* match) {
|
||||
++match;
|
||||
|
||||
size = match - ptr;
|
||||
if (val[size] == '\0') {
|
||||
if (memcmp(ptr, val, size) == 0) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
char buffer[128];
|
||||
memcpy(buffer, ptr, size);
|
||||
buffer[size] = '\0';
|
||||
if (rc_libretro_string_equal_nocase_wildcard(buffer, val))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (*match == ',');
|
||||
if (rc_libretro_match_token(val, ptr, size, &result))
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
} while (*match == ',');
|
||||
}
|
||||
else {
|
||||
/* a leading exclamation point means the provided value(s) are not forbidden (are allowed) */
|
||||
if (*match == '!')
|
||||
return !rc_libretro_match_value(val, &match[1]);
|
||||
|
||||
/* just a single value, attempt to match it */
|
||||
if (rc_libretro_match_token(val, match, strlen(match), &result))
|
||||
return result;
|
||||
}
|
||||
|
||||
/* a leading exclamation point means the provided value(s) are not forbidden (are allowed) */
|
||||
if (*match == '!')
|
||||
return !rc_libretro_match_value(val, &match[1]);
|
||||
|
||||
/* a leading less tahn means the provided value is the minimum allowed */
|
||||
if (*match == '<')
|
||||
return rc_libretro_numeric_less_than(val, &match[1]);
|
||||
|
||||
/* just a single value, attempt to match it */
|
||||
return rc_libretro_string_equal_nocase_wildcard(val, match);
|
||||
/* value did not match filters, assume it's allowed */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rc_libretro_is_setting_allowed(const rc_disallowed_setting_t* disallowed_settings, const char* setting, const char* value) {
|
||||
|
||||
@@ -38,6 +38,9 @@ void rc_buffer_destroy(rc_buffer_t* buffer)
|
||||
total += (int)(chunk->end - chunk->start);
|
||||
wasted += (int)(chunk->end - chunk->write);
|
||||
++count;
|
||||
#endif
|
||||
#ifdef DEBUG_BUFFERS
|
||||
printf("< free %p.%p\n", (void*)buffer, (void*)chunk);
|
||||
#endif
|
||||
free(chunk);
|
||||
chunk = next;
|
||||
@@ -70,6 +73,10 @@ uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount)
|
||||
if (!chunk->next)
|
||||
break;
|
||||
|
||||
#ifdef DEBUG_BUFFERS
|
||||
printf("> alloc %p.%p\n", (void*)buffer, (void*)chunk->next);
|
||||
#endif
|
||||
|
||||
chunk->next->start = (uint8_t*)chunk->next + chunk_header_size;
|
||||
chunk->next->write = chunk->next->start;
|
||||
chunk->next->end = (uint8_t*)chunk->next + alloc_size;
|
||||
|
||||
@@ -35,11 +35,11 @@ void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment
|
||||
|
||||
if (pointer != 0) {
|
||||
/* valid buffer, grab the next chunk */
|
||||
ptr = (void*)((char*)pointer + *offset);
|
||||
ptr = (void*)((uint8_t*)pointer + *offset);
|
||||
}
|
||||
else if (scratch != 0 && scratch_object_pointer_offset < sizeof(scratch->objs)) {
|
||||
/* only allocate one instance of each object type (indentified by scratch_object_pointer_offset) */
|
||||
void** scratch_object_pointer = (void**)((char*)&scratch->objs + scratch_object_pointer_offset);
|
||||
void** scratch_object_pointer = (void**)((uint8_t*)&scratch->objs + scratch_object_pointer_offset);
|
||||
ptr = *scratch_object_pointer;
|
||||
if (!ptr) {
|
||||
int32_t used;
|
||||
@@ -94,22 +94,223 @@ char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void rc_init_preparse_state(rc_preparse_state_t* preparse, lua_State* L, int funcs_ndx)
|
||||
{
|
||||
rc_init_parse_state(&preparse->parse, NULL, L, funcs_ndx);
|
||||
rc_init_parse_state_memrefs(&preparse->parse, &preparse->memrefs);
|
||||
}
|
||||
|
||||
void rc_destroy_preparse_state(rc_preparse_state_t* preparse)
|
||||
{
|
||||
rc_destroy_parse_state(&preparse->parse);
|
||||
}
|
||||
|
||||
void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse)
|
||||
{
|
||||
const uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs);
|
||||
const uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs);
|
||||
|
||||
if (preparse->parse.offset < 0)
|
||||
return;
|
||||
|
||||
if (memrefs) {
|
||||
memset(memrefs, 0, sizeof(*memrefs));
|
||||
preparse->parse.memrefs = memrefs;
|
||||
}
|
||||
|
||||
if (num_memrefs) {
|
||||
rc_memref_t* memref_items = RC_ALLOC_ARRAY(rc_memref_t, num_memrefs, &preparse->parse);
|
||||
|
||||
if (memrefs) {
|
||||
memrefs->memrefs.capacity = num_memrefs;
|
||||
memrefs->memrefs.items = memref_items;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_modified_memrefs) {
|
||||
rc_modified_memref_t* modified_memref_items =
|
||||
RC_ALLOC_ARRAY(rc_modified_memref_t, num_modified_memrefs, &preparse->parse);
|
||||
|
||||
if (memrefs) {
|
||||
memrefs->modified_memrefs.capacity = num_modified_memrefs;
|
||||
memrefs->modified_memrefs.items = modified_memref_items;
|
||||
}
|
||||
}
|
||||
|
||||
/* when preparsing, this structure will be allocated at the end. when it's allocated earlier
|
||||
* in the buffer, it could be followed by something aligned at 8 bytes. force the offset to
|
||||
* an 8-byte boundary */
|
||||
if (!memrefs) {
|
||||
rc_alloc(preparse->parse.buffer, &preparse->parse.offset, 0, 8, &preparse->parse.scratch, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rc_preparse_array_size(uint32_t needed, uint32_t minimum)
|
||||
{
|
||||
while (minimum < needed)
|
||||
minimum <<= 1;
|
||||
|
||||
return minimum;
|
||||
}
|
||||
|
||||
void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs)
|
||||
{
|
||||
uint32_t num_memrefs = rc_memrefs_count_memrefs(&preparse->memrefs);
|
||||
uint32_t num_modified_memrefs = rc_memrefs_count_modified_memrefs(&preparse->memrefs);
|
||||
uint32_t available;
|
||||
|
||||
if (preparse->parse.offset < 0)
|
||||
return;
|
||||
|
||||
if (num_memrefs) {
|
||||
rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
while (memref_list->count == memref_list->capacity) {
|
||||
if (!memref_list->next)
|
||||
break;
|
||||
|
||||
memref_list = memref_list->next;
|
||||
}
|
||||
|
||||
available = memref_list->capacity - memref_list->count;
|
||||
if (available < num_memrefs) {
|
||||
rc_memref_list_t* new_memref_list = (rc_memref_list_t*)calloc(1, sizeof(rc_memref_list_t));
|
||||
if (!new_memref_list)
|
||||
return;
|
||||
|
||||
new_memref_list->capacity = rc_preparse_array_size(num_memrefs - available, 16);
|
||||
new_memref_list->items = (rc_memref_t*)malloc(new_memref_list->capacity * sizeof(rc_memref_t));
|
||||
new_memref_list->allocated = 1;
|
||||
memref_list->next = new_memref_list;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_modified_memrefs) {
|
||||
rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
||||
while (modified_memref_list->count == modified_memref_list->capacity) {
|
||||
if (!modified_memref_list->next)
|
||||
break;
|
||||
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
}
|
||||
|
||||
available = modified_memref_list->capacity - modified_memref_list->count;
|
||||
if (available < num_modified_memrefs) {
|
||||
rc_modified_memref_list_t* new_modified_memref_list = (rc_modified_memref_list_t*)calloc(1, sizeof(rc_modified_memref_list_t));
|
||||
if (!new_modified_memref_list)
|
||||
return;
|
||||
|
||||
new_modified_memref_list->capacity = rc_preparse_array_size(num_modified_memrefs - available, 8);
|
||||
new_modified_memref_list->items = (rc_modified_memref_t*)malloc(new_modified_memref_list->capacity * sizeof(rc_modified_memref_t));
|
||||
new_modified_memref_list->allocated = 1;
|
||||
modified_memref_list->next = new_modified_memref_list;
|
||||
}
|
||||
}
|
||||
|
||||
preparse->parse.memrefs = memrefs;
|
||||
}
|
||||
|
||||
static void rc_preparse_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memrefs_t* memrefs)
|
||||
{
|
||||
if (rc_operand_is_memref(operand) || rc_operand_is_recall(operand)) {
|
||||
const rc_memref_t* src_memref = operand->value.memref;
|
||||
|
||||
if (src_memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
||||
const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
||||
for (; modified_memref_list; modified_memref_list = modified_memref_list->next) {
|
||||
const rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
||||
const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count;
|
||||
|
||||
for (; modified_memref < modified_memref_end; ++modified_memref) {
|
||||
if ((const rc_modified_memref_t*)src_memref == modified_memref) {
|
||||
rc_modified_memref_t* dst_modified_memref = rc_alloc_modified_memref(parse, modified_memref->memref.value.size,
|
||||
&modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier);
|
||||
|
||||
operand->value.memref = &dst_modified_memref->memref;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
for (; memref_list; memref_list = memref_list->next) {
|
||||
const rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_end = memref + memref_list->count;
|
||||
|
||||
for (; memref < memref_end; ++memref) {
|
||||
if (src_memref == memref) {
|
||||
operand->value.memref = rc_alloc_memref(parse, memref->address, memref->value.size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs)
|
||||
{
|
||||
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
||||
|
||||
for (; memref_list; memref_list = memref_list->next) {
|
||||
const rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_end = memref + memref_list->count;
|
||||
|
||||
for (; memref < memref_end; ++memref)
|
||||
rc_alloc_memref(parse, memref->address, memref->value.size);
|
||||
}
|
||||
|
||||
for (; modified_memref_list; modified_memref_list = modified_memref_list->next) {
|
||||
rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
||||
const rc_modified_memref_t* modified_memref_end = modified_memref + modified_memref_list->count;
|
||||
|
||||
for (; modified_memref < modified_memref_end; ++modified_memref) {
|
||||
rc_preparse_sync_operand(&modified_memref->parent, parse, memrefs);
|
||||
rc_preparse_sync_operand(&modified_memref->modifier, parse, memrefs);
|
||||
|
||||
rc_alloc_modified_memref(parse, modified_memref->memref.value.size,
|
||||
&modified_memref->parent, modified_memref->modifier_type, &modified_memref->modifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx)
|
||||
{
|
||||
#ifndef RC_DISABLE_LUA
|
||||
parse->L = L;
|
||||
parse->funcs_ndx = funcs_ndx;
|
||||
#else
|
||||
(void)L;
|
||||
(void)funcs_ndx;
|
||||
#endif
|
||||
|
||||
parse->buffer = buffer;
|
||||
|
||||
parse->offset = 0;
|
||||
parse->memrefs = NULL;
|
||||
parse->existing_memrefs = NULL;
|
||||
parse->variables = NULL;
|
||||
parse->measured_target = 0;
|
||||
parse->lines_read = 0;
|
||||
parse->addsource_oper = RC_OPERATOR_NONE;
|
||||
parse->addsource_parent.type = RC_OPERAND_NONE;
|
||||
parse->indirect_parent.type = RC_OPERAND_NONE;
|
||||
parse->remember.type = RC_OPERAND_NONE;
|
||||
parse->is_value = 0;
|
||||
parse->has_required_hits = 0;
|
||||
parse->measured_as_percent = 0;
|
||||
|
||||
parse->scratch.strings = NULL;
|
||||
}
|
||||
|
||||
void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx)
|
||||
{
|
||||
/* could use memset here, but rc_parse_state_t contains a 512 byte buffer that doesn't need to be initialized */
|
||||
parse->offset = 0;
|
||||
parse->L = L;
|
||||
parse->funcs_ndx = funcs_ndx;
|
||||
parse->buffer = buffer;
|
||||
parse->scratch.strings = NULL;
|
||||
rc_buffer_init(&parse->scratch.buffer);
|
||||
memset(&parse->scratch.objs, 0, sizeof(parse->scratch.objs));
|
||||
parse->first_memref = 0;
|
||||
parse->variables = 0;
|
||||
parse->measured_target = 0;
|
||||
parse->lines_read = 0;
|
||||
parse->has_required_hits = 0;
|
||||
parse->measured_as_percent = 0;
|
||||
|
||||
rc_reset_parse_state(parse, buffer, L, funcs_ndx);
|
||||
}
|
||||
|
||||
void rc_destroy_parse_state(rc_parse_state_t* parse)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "rc_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static int rc_test_condition_compare(uint32_t value1, uint32_t value2, uint8_t oper) {
|
||||
@@ -15,7 +16,7 @@ static int rc_test_condition_compare(uint32_t value1, uint32_t value2, uint8_t o
|
||||
}
|
||||
}
|
||||
|
||||
static char rc_condition_determine_comparator(const rc_condition_t* self) {
|
||||
static uint8_t rc_condition_determine_comparator(const rc_condition_t* self) {
|
||||
switch (self->oper) {
|
||||
case RC_OPERATOR_EQ:
|
||||
case RC_OPERATOR_NE:
|
||||
@@ -31,7 +32,8 @@ static char rc_condition_determine_comparator(const rc_condition_t* self) {
|
||||
}
|
||||
|
||||
if ((self->operand1.type == RC_OPERAND_ADDRESS || self->operand1.type == RC_OPERAND_DELTA) &&
|
||||
!self->operand1.value.memref->value.is_indirect && !rc_operand_is_float(&self->operand1)) {
|
||||
/* TODO: allow modified memref comparisons */
|
||||
self->operand1.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && !rc_operand_is_float(&self->operand1)) {
|
||||
/* left side is an integer memory reference */
|
||||
int needs_translate = (self->operand1.size != self->operand1.value.memref->value.size);
|
||||
|
||||
@@ -43,7 +45,7 @@ static char rc_condition_determine_comparator(const rc_condition_t* self) {
|
||||
return needs_translate ? RC_PROCESSING_COMPARE_DELTA_TO_CONST_TRANSFORMED : RC_PROCESSING_COMPARE_DELTA_TO_CONST;
|
||||
}
|
||||
else if ((self->operand2.type == RC_OPERAND_ADDRESS || self->operand2.type == RC_OPERAND_DELTA) &&
|
||||
!self->operand2.value.memref->value.is_indirect && !rc_operand_is_float(&self->operand2)) {
|
||||
self->operand2.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF && !rc_operand_is_float(&self->operand2)) {
|
||||
/* right side is an integer memory reference */
|
||||
const int is_same_memref = (self->operand1.value.memref == self->operand2.value.memref);
|
||||
needs_translate |= (self->operand2.size != self->operand2.value.memref->value.size);
|
||||
@@ -161,17 +163,45 @@ static int rc_parse_operator(const char** memaddr) {
|
||||
}
|
||||
}
|
||||
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect) {
|
||||
rc_condition_t* self;
|
||||
void rc_condition_convert_to_operand(const rc_condition_t* condition, rc_operand_t* operand, rc_parse_state_t* parse) {
|
||||
if (condition->oper == RC_OPERATOR_NONE) {
|
||||
if (operand != &condition->operand1)
|
||||
memcpy(operand, &condition->operand1, sizeof(*operand));
|
||||
}
|
||||
else {
|
||||
uint8_t new_size = RC_MEMSIZE_32_BITS;
|
||||
if (rc_operand_is_float(&condition->operand1) || rc_operand_is_float(&condition->operand2))
|
||||
new_size = RC_MEMSIZE_FLOAT;
|
||||
|
||||
/* NOTE: this makes the operand include the modification, but we have to also
|
||||
* leave the modification in the condition so the condition reflects the actual
|
||||
* definition. This doesn't affect the evaluation logic since this method is only
|
||||
* called for combining conditions and Measured, and the Measured handling function
|
||||
* ignores the operator assuming it's been handled by a modified memref chain */
|
||||
operand->value.memref = (rc_memref_t*)rc_alloc_modified_memref(parse,
|
||||
new_size, &condition->operand1, condition->oper, &condition->operand2);
|
||||
|
||||
/* not actually an address, just a non-delta memref read */
|
||||
operand->type = operand->memref_access_type = RC_OPERAND_ADDRESS;
|
||||
|
||||
operand->size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_condition_t * self = RC_ALLOC(rc_condition_t, parse);
|
||||
rc_parse_condition_internal(self, memaddr, parse);
|
||||
return (parse->offset < 0) ? NULL : self;
|
||||
}
|
||||
|
||||
void rc_parse_condition_internal(rc_condition_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
const char* aux;
|
||||
int result;
|
||||
int can_modify = 0;
|
||||
|
||||
aux = *memaddr;
|
||||
self = RC_ALLOC(rc_condition_t, parse);
|
||||
self->current_hits = 0;
|
||||
self->is_true = 0;
|
||||
self->pause = 0;
|
||||
self->optimized_comparator = RC_PROCESSING_COMPARE_DEFAULT;
|
||||
|
||||
if (*aux != 0 && aux[1] == ':') {
|
||||
@@ -194,8 +224,11 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
parse->measured_as_percent = 1;
|
||||
self->type = RC_CONDITION_MEASURED;
|
||||
break;
|
||||
|
||||
/* e f h j l s u v w x y */
|
||||
default: parse->offset = RC_INVALID_CONDITION_TYPE; return 0;
|
||||
default:
|
||||
parse->offset = RC_INVALID_CONDITION_TYPE;
|
||||
return;
|
||||
}
|
||||
|
||||
aux += 2;
|
||||
@@ -204,79 +237,63 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
self->type = RC_CONDITION_STANDARD;
|
||||
}
|
||||
|
||||
result = rc_parse_operand(&self->operand1, &aux, is_indirect, parse);
|
||||
result = rc_parse_operand(&self->operand1, &aux, parse);
|
||||
if (result < 0) {
|
||||
parse->offset = result;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
result = rc_parse_operator(&aux);
|
||||
if (result < 0) {
|
||||
parse->offset = result;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
self->oper = (char)result;
|
||||
switch (self->oper) {
|
||||
case RC_OPERATOR_NONE:
|
||||
/* non-modifying statements must have a second operand */
|
||||
if (!can_modify) {
|
||||
/* measured does not require a second operand when used in a value */
|
||||
if (self->type != RC_CONDITION_MEASURED) {
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return 0;
|
||||
}
|
||||
self->oper = (uint8_t)result;
|
||||
|
||||
if (self->oper == RC_OPERATOR_NONE) {
|
||||
/* non-modifying statements must have a second operand */
|
||||
if (!can_modify) {
|
||||
/* measured does not require a second operand when used in a value */
|
||||
if (self->type != RC_CONDITION_MEASURED) {
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* provide dummy operand of '1' and no required hits */
|
||||
self->operand2.type = RC_OPERAND_CONST;
|
||||
self->operand2.value.num = 1;
|
||||
self->required_hits = 0;
|
||||
*memaddr = aux;
|
||||
return self;
|
||||
/* provide dummy operand of '1' and no required hits */
|
||||
rc_operand_set_const(&self->operand2, 1);
|
||||
self->required_hits = 0;
|
||||
*memaddr = aux;
|
||||
return;
|
||||
}
|
||||
|
||||
case RC_OPERATOR_MULT:
|
||||
case RC_OPERATOR_DIV:
|
||||
case RC_OPERATOR_AND:
|
||||
case RC_OPERATOR_XOR:
|
||||
case RC_OPERATOR_MOD:
|
||||
case RC_OPERATOR_ADD:
|
||||
case RC_OPERATOR_SUB:
|
||||
/* modifying operators are only valid on modifying statements */
|
||||
if (can_modify)
|
||||
if (can_modify && !rc_operator_is_modifying(self->oper)) {
|
||||
/* comparison operators are not valid on modifying statements */
|
||||
switch (self->type) {
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
case RC_CONDITION_REMEMBER:
|
||||
/* prevent parse errors on legacy achievements where a condition was present before changing the type */
|
||||
self->oper = RC_OPERATOR_NONE;
|
||||
break;
|
||||
/* fallthrough */
|
||||
|
||||
default:
|
||||
/* comparison operators are not valid on modifying statements */
|
||||
if (can_modify) {
|
||||
switch (self->type) {
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
case RC_CONDITION_REMEMBER:
|
||||
/* prevent parse errors on legacy achievements where a condition was present before changing the type */
|
||||
self->oper = RC_OPERATOR_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
result = rc_parse_operand(&self->operand2, &aux, is_indirect, parse);
|
||||
result = rc_parse_operand(&self->operand2, &aux, parse);
|
||||
if (result < 0) {
|
||||
parse->offset = result;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->oper == RC_OPERATOR_NONE) {
|
||||
/* if operator is none, explicitly clear out the right side */
|
||||
self->operand2.type = RC_OPERAND_CONST;
|
||||
self->operand2.value.num = 0;
|
||||
rc_operand_set_const(&self->operand2, 0);
|
||||
}
|
||||
|
||||
if (*aux == '(') {
|
||||
@@ -285,7 +302,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
|
||||
if (end == aux || *end != ')') {
|
||||
parse->offset = RC_INVALID_REQUIRED_HITS;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if operator is none, explicitly clear out the required hits */
|
||||
@@ -302,7 +319,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
|
||||
if (end == aux || *end != '.') {
|
||||
parse->offset = RC_INVALID_REQUIRED_HITS;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if operator is none, explicitly clear out the required hits */
|
||||
@@ -321,7 +338,140 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
self->optimized_comparator = rc_condition_determine_comparator(self);
|
||||
|
||||
*memaddr = aux;
|
||||
return self;
|
||||
}
|
||||
|
||||
void rc_condition_update_parse_state(rc_condition_t* condition, rc_parse_state_t* parse) {
|
||||
/* type of values in the chain are determined by the parent.
|
||||
* the last element of a chain is determined by the operand
|
||||
*
|
||||
* 1 + 1.5 + 1.75 + 1.0 => (int)1 + (int)1 + (int)1 + (float)1 = (float)4.0
|
||||
* 1.0 + 1.5 + 1.75 + 1.0 => (float)1.0 + (float)1.5 + (float)1.75 + (float)1.0 = (float)5.25
|
||||
* 1.0 + 1.5 + 1.75 + 1 => (float)1.0 + (float)1.5 + (float)1.75 + (int)1 = (int)5
|
||||
*/
|
||||
|
||||
switch (condition->type) {
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
if (condition->oper != RC_OPERAND_NONE)
|
||||
rc_condition_convert_to_operand(condition, &parse->indirect_parent, parse);
|
||||
else
|
||||
memcpy(&parse->indirect_parent, &condition->operand1, sizeof(parse->indirect_parent));
|
||||
|
||||
break;
|
||||
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
if (parse->addsource_parent.type == RC_OPERAND_NONE) {
|
||||
rc_condition_convert_to_operand(condition, &parse->addsource_parent, parse);
|
||||
}
|
||||
else {
|
||||
rc_operand_t cond_operand;
|
||||
/* type determined by parent */
|
||||
const uint8_t new_size = rc_operand_is_float(&parse->addsource_parent) ? RC_MEMSIZE_FLOAT : RC_MEMSIZE_32_BITS;
|
||||
|
||||
rc_condition_convert_to_operand(condition, &cond_operand, parse);
|
||||
rc_operand_addsource(&cond_operand, parse, new_size);
|
||||
memcpy(&parse->addsource_parent, &cond_operand, sizeof(cond_operand));
|
||||
}
|
||||
|
||||
parse->addsource_oper = RC_OPERATOR_ADD;
|
||||
parse->indirect_parent.type = RC_OPERAND_NONE;
|
||||
break;
|
||||
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
if (parse->addsource_parent.type == RC_OPERAND_NONE) {
|
||||
rc_condition_convert_to_operand(condition, &parse->addsource_parent, parse);
|
||||
parse->addsource_oper = RC_OPERATOR_SUB_PARENT;
|
||||
}
|
||||
else {
|
||||
rc_operand_t cond_operand;
|
||||
/* type determined by parent */
|
||||
const uint8_t new_size = rc_operand_is_float(&parse->addsource_parent) ? RC_MEMSIZE_FLOAT : RC_MEMSIZE_32_BITS;
|
||||
|
||||
if (parse->addsource_oper == RC_OPERATOR_ADD && !rc_operand_is_memref(&parse->addsource_parent)) {
|
||||
/* if the previous element was a constant we have to turn it into a memref by adding zero */
|
||||
rc_modified_memref_t* memref;
|
||||
rc_operand_t zero;
|
||||
rc_operand_set_const(&zero, 0);
|
||||
memref = rc_alloc_modified_memref(parse,
|
||||
parse->addsource_parent.size, &parse->addsource_parent, RC_OPERATOR_ADD, &zero);
|
||||
parse->addsource_parent.value.memref = (rc_memref_t*)memref;
|
||||
parse->addsource_parent.type = RC_OPERAND_ADDRESS;
|
||||
}
|
||||
else if (parse->addsource_oper == RC_OPERATOR_SUB_PARENT) {
|
||||
/* if the previous element was also a SubSource, we have to insert a 0 and start subtracting from there */
|
||||
rc_modified_memref_t* negate;
|
||||
rc_operand_t zero;
|
||||
|
||||
if (rc_operand_is_float(&parse->addsource_parent))
|
||||
rc_operand_set_float_const(&zero, 0.0);
|
||||
else
|
||||
rc_operand_set_const(&zero, 0);
|
||||
|
||||
negate = rc_alloc_modified_memref(parse, new_size, &parse->addsource_parent, RC_OPERATOR_SUB_PARENT, &zero);
|
||||
parse->addsource_parent.value.memref = (rc_memref_t*)negate;
|
||||
parse->addsource_parent.size = zero.size;
|
||||
}
|
||||
|
||||
/* subtract the condition from the chain */
|
||||
parse->addsource_oper = rc_operand_is_memref(&parse->addsource_parent) ? RC_OPERATOR_SUB : RC_OPERATOR_SUB_PARENT;
|
||||
rc_condition_convert_to_operand(condition, &cond_operand, parse);
|
||||
rc_operand_addsource(&cond_operand, parse, new_size);
|
||||
memcpy(&parse->addsource_parent, &cond_operand, sizeof(cond_operand));
|
||||
|
||||
/* indicate the next value can be added to the chain */
|
||||
parse->addsource_oper = RC_OPERATOR_ADD;
|
||||
}
|
||||
|
||||
parse->indirect_parent.type = RC_OPERAND_NONE;
|
||||
break;
|
||||
|
||||
case RC_CONDITION_REMEMBER:
|
||||
rc_condition_convert_to_operand(condition, &condition->operand1, parse);
|
||||
|
||||
if (parse->addsource_parent.type != RC_OPERAND_NONE) {
|
||||
/* type determined by leaf */
|
||||
rc_operand_addsource(&condition->operand1, parse, condition->operand1.size);
|
||||
}
|
||||
|
||||
memcpy(&parse->remember, &condition->operand1, sizeof(parse->remember));
|
||||
|
||||
parse->addsource_parent.type = RC_OPERAND_NONE;
|
||||
parse->indirect_parent.type = RC_OPERAND_NONE;
|
||||
break;
|
||||
|
||||
case RC_CONDITION_MEASURED:
|
||||
/* Measured condition can have modifiers in values */
|
||||
if (parse->is_value) {
|
||||
switch (condition->oper) {
|
||||
case RC_OPERATOR_AND:
|
||||
case RC_OPERATOR_XOR:
|
||||
case RC_OPERATOR_DIV:
|
||||
case RC_OPERATOR_MULT:
|
||||
case RC_OPERATOR_MOD:
|
||||
case RC_OPERATOR_ADD:
|
||||
case RC_OPERATOR_SUB:
|
||||
rc_condition_convert_to_operand(condition, &condition->operand1, parse);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* fallthrough */ /* to default */
|
||||
|
||||
default:
|
||||
if (parse->addsource_parent.type != RC_OPERAND_NONE) {
|
||||
/* type determined by leaf */
|
||||
rc_operand_addsource(&condition->operand1, parse, condition->operand1.size);
|
||||
|
||||
if (parse->buffer)
|
||||
condition->optimized_comparator = rc_condition_determine_comparator(condition);
|
||||
}
|
||||
|
||||
parse->addsource_parent.type = RC_OPERAND_NONE;
|
||||
parse->indirect_parent.type = RC_OPERAND_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int rc_condition_is_combining(const rc_condition_t* self) {
|
||||
@@ -500,41 +650,35 @@ static int rc_test_condition_compare_delta_to_memref_transformed(rc_condition_t*
|
||||
int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state) {
|
||||
rc_typed_value_t value1, value2;
|
||||
|
||||
if (eval_state->add_value.type != RC_VALUE_TYPE_NONE) {
|
||||
/* if there's an accumulator, we can't use the optimized comparators */
|
||||
rc_evaluate_operand(&value1, &self->operand1, eval_state);
|
||||
rc_typed_value_add(&value1, &eval_state->add_value);
|
||||
} else {
|
||||
/* use an optimized comparator whenever possible */
|
||||
switch (self->optimized_comparator) {
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_CONST:
|
||||
return rc_test_condition_compare_memref_to_const(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_DELTA:
|
||||
return rc_test_condition_compare_memref_to_delta(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF:
|
||||
return rc_test_condition_compare_memref_to_memref(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_CONST:
|
||||
return rc_test_condition_compare_delta_to_const(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_MEMREF:
|
||||
return rc_test_condition_compare_delta_to_memref(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_CONST_TRANSFORMED:
|
||||
return rc_test_condition_compare_memref_to_const_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_DELTA_TRANSFORMED:
|
||||
return rc_test_condition_compare_memref_to_delta_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF_TRANSFORMED:
|
||||
return rc_test_condition_compare_memref_to_memref_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_CONST_TRANSFORMED:
|
||||
return rc_test_condition_compare_delta_to_const_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_MEMREF_TRANSFORMED:
|
||||
return rc_test_condition_compare_delta_to_memref_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_ALWAYS_TRUE:
|
||||
return 1;
|
||||
case RC_PROCESSING_COMPARE_ALWAYS_FALSE:
|
||||
return 0;
|
||||
default:
|
||||
rc_evaluate_operand(&value1, &self->operand1, eval_state);
|
||||
break;
|
||||
}
|
||||
/* use an optimized comparator whenever possible */
|
||||
switch (self->optimized_comparator) {
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_CONST:
|
||||
return rc_test_condition_compare_memref_to_const(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_DELTA:
|
||||
return rc_test_condition_compare_memref_to_delta(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF:
|
||||
return rc_test_condition_compare_memref_to_memref(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_CONST:
|
||||
return rc_test_condition_compare_delta_to_const(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_MEMREF:
|
||||
return rc_test_condition_compare_delta_to_memref(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_CONST_TRANSFORMED:
|
||||
return rc_test_condition_compare_memref_to_const_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_DELTA_TRANSFORMED:
|
||||
return rc_test_condition_compare_memref_to_delta_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_MEMREF_TO_MEMREF_TRANSFORMED:
|
||||
return rc_test_condition_compare_memref_to_memref_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_CONST_TRANSFORMED:
|
||||
return rc_test_condition_compare_delta_to_const_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_DELTA_TO_MEMREF_TRANSFORMED:
|
||||
return rc_test_condition_compare_delta_to_memref_transformed(self);
|
||||
case RC_PROCESSING_COMPARE_ALWAYS_TRUE:
|
||||
return 1;
|
||||
case RC_PROCESSING_COMPARE_ALWAYS_FALSE:
|
||||
return 0;
|
||||
default:
|
||||
rc_evaluate_operand(&value1, &self->operand1, eval_state);
|
||||
break;
|
||||
}
|
||||
|
||||
rc_evaluate_operand(&value2, &self->operand2, eval_state);
|
||||
@@ -548,38 +692,5 @@ void rc_evaluate_condition_value(rc_typed_value_t* value, rc_condition_t* self,
|
||||
rc_evaluate_operand(value, &self->operand1, eval_state);
|
||||
rc_evaluate_operand(&amount, &self->operand2, eval_state);
|
||||
|
||||
switch (self->oper) {
|
||||
case RC_OPERATOR_MULT:
|
||||
rc_typed_value_multiply(value, &amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_DIV:
|
||||
rc_typed_value_divide(value, &amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_AND:
|
||||
rc_typed_value_convert(value, RC_VALUE_TYPE_UNSIGNED);
|
||||
rc_typed_value_convert(&amount, RC_VALUE_TYPE_UNSIGNED);
|
||||
value->value.u32 &= amount.value.u32;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_XOR:
|
||||
rc_typed_value_convert(value, RC_VALUE_TYPE_UNSIGNED);
|
||||
rc_typed_value_convert(&amount, RC_VALUE_TYPE_UNSIGNED);
|
||||
value->value.u32 ^= amount.value.u32;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_MOD:
|
||||
rc_typed_value_modulus(value, &amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_ADD:
|
||||
rc_typed_value_add(value, &amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_SUB:
|
||||
rc_typed_value_negate(&amount);
|
||||
rc_typed_value_add(value, &amount);
|
||||
break;
|
||||
}
|
||||
rc_typed_value_combine(value, &amount, self->oper);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -72,6 +72,9 @@ const char* rc_console_name(uint32_t console_id)
|
||||
case RC_CONSOLE_FAIRCHILD_CHANNEL_F:
|
||||
return "Fairchild Channel F";
|
||||
|
||||
case RC_CONSOLE_FAMICOM_DISK_SYSTEM:
|
||||
return "Famicom Disk System";
|
||||
|
||||
case RC_CONSOLE_FM_TOWNS:
|
||||
return "FM Towns";
|
||||
|
||||
@@ -380,14 +383,18 @@ static const rc_memory_regions_t rc_memory_regions_colecovision = { _rc_memory_r
|
||||
/* ===== Commodore 64 ===== */
|
||||
/* https://www.c64-wiki.com/wiki/Memory_Map */
|
||||
/* https://sta.c64.org/cbm64mem.html */
|
||||
/* NOTE: Several blocks of C64 memory can be bank-switched for ROM data (see https://www.c64-wiki.com/wiki/Bank_Switching).
|
||||
* Achievement triggers rely on values changing, so we don't really need to look at the ROM data.
|
||||
* The achievement logic assumes the RAM data is always present in the bankable blocks. As such,
|
||||
* clients providing memory to achievements should always return the RAM values at the queried address. */
|
||||
static const rc_memory_region_t _rc_memory_regions_c64[] = {
|
||||
{ 0x000000U, 0x0003FFU, 0x000000U, RC_MEMORY_TYPE_SYSTEM_RAM, "Kernel RAM" },
|
||||
{ 0x000400U, 0x0007FFU, 0x000400U, RC_MEMORY_TYPE_VIDEO_RAM, "Screen RAM" },
|
||||
{ 0x000800U, 0x009FFFU, 0x000800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* BASIC Program Storage Area */
|
||||
{ 0x00A000U, 0x00BFFFU, 0x00A000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* Machine Language Storage Area / BASIC ROM Area */
|
||||
{ 0x00C000U, 0x00CFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* Machine Language Storage Area */
|
||||
{ 0x00D000U, 0x00DFFFU, 0x00D000U, RC_MEMORY_TYPE_SYSTEM_RAM, "I/O Area" }, /* also Character ROM */
|
||||
{ 0x00E000U, 0x00FFFFU, 0x00E000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* Machine Language Storage Area / Kernal ROM */
|
||||
{ 0x000800U, 0x009FFFU, 0x000800U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* BASIC area. $8000-$9FFF can bank to cartridge ROM */
|
||||
{ 0x00A000U, 0x00BFFFU, 0x00A000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* can bank to BASIC ROM or cartridge ROM */
|
||||
{ 0x00C000U, 0x00CFFFU, 0x00C000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x00D000U, 0x00DFFFU, 0x00D000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* can bank to I/O Area or character ROM */
|
||||
{ 0x00E000U, 0x00FFFFU, 0x00E000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" }, /* can bank to kernel ROM */
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_c64 = { _rc_memory_regions_c64, 7 };
|
||||
|
||||
@@ -423,6 +430,24 @@ static const rc_memory_region_t _rc_memory_regions_fairchild_channel_f[] = {
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_fairchild_channel_f = { _rc_memory_regions_fairchild_channel_f, 4 };
|
||||
|
||||
/* ===== Famicon Disk System ===== */
|
||||
/* https://fms.komkon.org/EMUL8/NES.html */
|
||||
static const rc_memory_region_t _rc_memory_regions_famicom_disk_system[] = {
|
||||
{ 0x0000U, 0x07FFU, 0x0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x0800U, 0x0FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */
|
||||
{ 0x1000U, 0x17FFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */
|
||||
{ 0x1800U, 0x1FFFU, 0x0000U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirror RAM" }, /* duplicates memory from $0000-$07FF */
|
||||
{ 0x2000U, 0x2007U, 0x2000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "PPU Register" },
|
||||
{ 0x2008U, 0x3FFFU, 0x2008U, RC_MEMORY_TYPE_VIRTUAL_RAM, "Mirrored PPU Register" }, /* repeats every 8 bytes */
|
||||
{ 0x4000U, 0x4017U, 0x4000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O register" },
|
||||
{ 0x4018U, 0x401FU, 0x4018U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "APU and I/O test register" },
|
||||
{ 0x4020U, 0x40FFU, 0x4020U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "FDS I/O registers"},
|
||||
{ 0x4100U, 0x5FFFU, 0x4100U, RC_MEMORY_TYPE_READONLY, "Cartridge data"}, /* varies by mapper */
|
||||
{ 0x6000U, 0xDFFFU, 0x6000U, RC_MEMORY_TYPE_SYSTEM_RAM, "FDS RAM"},
|
||||
{ 0xE000U, 0xFFFFU, 0xE000U, RC_MEMORY_TYPE_READONLY, "FDS BIOS ROM"},
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_famicom_disk_system = { _rc_memory_regions_famicom_disk_system, 12 };
|
||||
|
||||
/* ===== GameBoy / MegaDuck ===== */
|
||||
static const rc_memory_region_t _rc_memory_regions_gameboy[] = {
|
||||
{ 0x000000U, 0x0000FFU, 0x000000U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "Interrupt vector" },
|
||||
@@ -694,18 +719,6 @@ static const rc_memory_region_t _rc_memory_regions_nes[] = {
|
||||
{ 0x4020U, 0x5FFFU, 0x4020U, RC_MEMORY_TYPE_READONLY, "Cartridge data"}, /* varies by mapper */
|
||||
{ 0x6000U, 0x7FFFU, 0x6000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM"},
|
||||
{ 0x8000U, 0xFFFFU, 0x8000U, RC_MEMORY_TYPE_READONLY, "Cartridge ROM"},
|
||||
|
||||
/* NOTE: these are the correct mappings for FDS: https://fms.komkon.org/EMUL8/NES.html
|
||||
* 0x6000-0xDFFF is RAM on the FDS system and 0xE000-0xFFFF is FDS BIOS.
|
||||
* If the core implements a memory map, we should still be able to translate the addresses
|
||||
* correctly as we only use the classifications when a memory map is not provided
|
||||
|
||||
{ 0x4020U, 0x40FFU, 0x4020U, RC_MEMORY_TYPE_HARDWARE_CONTROLLER, "FDS I/O registers"},
|
||||
{ 0x4100U, 0x5FFFU, 0x4100U, RC_MEMORY_TYPE_READONLY, "Cartridge data"}, // varies by mapper
|
||||
{ 0x6000U, 0xDFFFU, 0x6000U, RC_MEMORY_TYPE_SYSTEM_RAM, "FDS RAM"},
|
||||
{ 0xE000U, 0xFFFFU, 0xE000U, RC_MEMORY_TYPE_READONLY, "FDS BIOS ROM"},
|
||||
|
||||
*/
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_nes = { _rc_memory_regions_nes, 11 };
|
||||
|
||||
@@ -868,10 +881,18 @@ static const rc_memory_regions_t rc_memory_regions_scv = { _rc_memory_regions_sc
|
||||
/* ===== Super Nintendo ===== */
|
||||
/* https://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map#LoROM */
|
||||
static const rc_memory_region_t _rc_memory_regions_snes[] = {
|
||||
{ 0x000000U, 0x01FFFFU, 0x7E0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
{ 0x020000U, 0x03FFFFU, 0xFE0000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" }
|
||||
{ 0x000000U, 0x01FFFFU, 0x07E0000U, RC_MEMORY_TYPE_SYSTEM_RAM, "System RAM" },
|
||||
/* Cartridge RAM here could be in a variety of places in SNES memory, depending on the ROM type.
|
||||
* Due to this, we place Cartridge RAM outside of the possible native addressing space.
|
||||
* Note that this also covers SA-1 BW-RAM (which is exposed as RETRO_MEMORY_SAVE_RAM for libretro).
|
||||
*/
|
||||
{ 0x020000U, 0x09FFFFU, 0x1000000U, RC_MEMORY_TYPE_SAVE_RAM, "Cartridge RAM" },
|
||||
/* I-RAM on the SA-1 is normally at 0x003000. However, this address typically just has a mirror of System RAM for other ROM types.
|
||||
* To avoid conflicts, don't use 0x003000, instead map it outside of the possible native addressing space.
|
||||
*/
|
||||
{ 0x0A0000U, 0x0A07FFU, 0x1080000U, RC_MEMORY_TYPE_SYSTEM_RAM, "I-RAM (SA-1)" }
|
||||
};
|
||||
static const rc_memory_regions_t rc_memory_regions_snes = { _rc_memory_regions_snes, 2 };
|
||||
static const rc_memory_regions_t rc_memory_regions_snes = { _rc_memory_regions_snes, 3 };
|
||||
|
||||
/* ===== Thomson TO8 ===== */
|
||||
/* https://github.com/mamedev/mame/blob/master/src/mame/drivers/thomson.cpp#L1617 */
|
||||
@@ -1046,7 +1067,10 @@ const rc_memory_regions_t* rc_console_memory_regions(uint32_t console_id)
|
||||
|
||||
case RC_CONSOLE_FAIRCHILD_CHANNEL_F:
|
||||
return &rc_memory_regions_fairchild_channel_f;
|
||||
|
||||
|
||||
case RC_CONSOLE_FAMICOM_DISK_SYSTEM:
|
||||
return &rc_memory_regions_famicom_disk_system;
|
||||
|
||||
case RC_CONSOLE_GAMEBOY:
|
||||
return &rc_memory_regions_gameboy;
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
if (*memaddr && *memaddr != ':') {
|
||||
found |= RC_LBOARD_START;
|
||||
rc_parse_trigger_internal(&self->start, &memaddr, parse);
|
||||
self->start.memrefs = 0;
|
||||
}
|
||||
}
|
||||
else if ((memaddr[0] == 'c' || memaddr[0] == 'C') &&
|
||||
@@ -44,7 +43,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
if (*memaddr && *memaddr != ':') {
|
||||
found |= RC_LBOARD_CANCEL;
|
||||
rc_parse_trigger_internal(&self->cancel, &memaddr, parse);
|
||||
self->cancel.memrefs = 0;
|
||||
}
|
||||
}
|
||||
else if ((memaddr[0] == 's' || memaddr[0] == 'S') &&
|
||||
@@ -59,7 +57,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
if (*memaddr && *memaddr != ':') {
|
||||
found |= RC_LBOARD_SUBMIT;
|
||||
rc_parse_trigger_internal(&self->submit, &memaddr, parse);
|
||||
self->submit.memrefs = 0;
|
||||
}
|
||||
}
|
||||
else if ((memaddr[0] == 'v' || memaddr[0] == 'V') &&
|
||||
@@ -74,7 +71,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
if (*memaddr && *memaddr != ':') {
|
||||
found |= RC_LBOARD_VALUE;
|
||||
rc_parse_value_internal(&self->value, &memaddr, parse);
|
||||
self->value.memrefs = 0;
|
||||
}
|
||||
}
|
||||
else if ((memaddr[0] == 'p' || memaddr[0] == 'P') &&
|
||||
@@ -91,7 +87,6 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
|
||||
self->progress = RC_ALLOC(rc_value_t, parse);
|
||||
rc_parse_value_internal(self->progress, &memaddr, parse);
|
||||
self->progress->memrefs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,44 +125,55 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
}
|
||||
|
||||
self->state = RC_LBOARD_STATE_WAITING;
|
||||
self->has_memrefs = 0;
|
||||
}
|
||||
|
||||
int rc_lboard_size(const char* memaddr) {
|
||||
rc_lboard_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_memref_t* first_memref;
|
||||
rc_init_parse_state(&parse, 0, 0, 0);
|
||||
rc_init_parse_state_memrefs(&parse, &first_memref);
|
||||
rc_lboard_with_memrefs_t* lboard;
|
||||
rc_preparse_state_t preparse;
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
|
||||
self = RC_ALLOC(rc_lboard_t, &parse);
|
||||
rc_parse_lboard_internal(self, memaddr, &parse);
|
||||
lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse);
|
||||
rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(NULL, &preparse);
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return parse.offset;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) {
|
||||
rc_lboard_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_lboard_with_memrefs_t* lboard;
|
||||
rc_preparse_state_t preparse;
|
||||
|
||||
if (!buffer || !memaddr)
|
||||
return 0;
|
||||
|
||||
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
|
||||
rc_init_preparse_state(&preparse, L, funcs_ndx);
|
||||
lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse);
|
||||
rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse);
|
||||
|
||||
self = RC_ALLOC(rc_lboard_t, &parse);
|
||||
rc_init_parse_state_memrefs(&parse, &self->memrefs);
|
||||
rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx);
|
||||
lboard = RC_ALLOC(rc_lboard_with_memrefs_t, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(&lboard->memrefs, &preparse);
|
||||
|
||||
rc_parse_lboard_internal(self, memaddr, &parse);
|
||||
rc_parse_lboard_internal(&lboard->lboard, memaddr, &preparse.parse);
|
||||
lboard->lboard.has_memrefs = 1;
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return (parse.offset >= 0) ? self : 0;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return (preparse.parse.offset >= 0) ? &lboard->lboard : NULL;
|
||||
}
|
||||
|
||||
static void rc_update_lboard_memrefs(rc_lboard_t* self, rc_peek_t peek, void* ud) {
|
||||
if (self->has_memrefs) {
|
||||
rc_lboard_with_memrefs_t* lboard = (rc_lboard_with_memrefs_t*)self;
|
||||
rc_update_memref_values(&lboard->memrefs, peek, ud);
|
||||
}
|
||||
}
|
||||
|
||||
int rc_evaluate_lboard(rc_lboard_t* self, int32_t* value, rc_peek_t peek, void* peek_ud, lua_State* L) {
|
||||
int start_ok, cancel_ok, submit_ok;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, peek_ud);
|
||||
rc_update_lboard_memrefs(self, peek, peek_ud);
|
||||
|
||||
if (self->state == RC_LBOARD_STATE_INACTIVE || self->state == RC_LBOARD_STATE_DISABLED)
|
||||
return RC_LBOARD_STATE_INACTIVE;
|
||||
|
||||
@@ -6,41 +6,232 @@
|
||||
|
||||
#define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF
|
||||
|
||||
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size, uint8_t is_indirect) {
|
||||
rc_memref_t** next_memref;
|
||||
rc_memref_t* memref;
|
||||
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size) {
|
||||
rc_memref_list_t* memref_list = NULL;
|
||||
rc_memref_t* memref = NULL;
|
||||
int i;
|
||||
|
||||
if (!is_indirect) {
|
||||
/* attempt to find an existing memref that can be shared */
|
||||
next_memref = parse->first_memref;
|
||||
while (*next_memref) {
|
||||
memref = *next_memref;
|
||||
if (!memref->value.is_indirect && memref->address == address && memref->value.size == size)
|
||||
return memref;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (i == 0) {
|
||||
if (!parse->existing_memrefs)
|
||||
continue;
|
||||
|
||||
next_memref = &memref->next;
|
||||
memref_list = &parse->existing_memrefs->memrefs;
|
||||
}
|
||||
else {
|
||||
memref_list = &parse->memrefs->memrefs;
|
||||
}
|
||||
|
||||
/* no match found, create a new entry */
|
||||
memref = RC_ALLOC_SCRATCH(rc_memref_t, parse);
|
||||
*next_memref = memref;
|
||||
do
|
||||
{
|
||||
const rc_memref_t* memref_stop;
|
||||
|
||||
memref = memref_list->items;
|
||||
memref_stop = memref + memref_list->count;
|
||||
|
||||
for (; memref < memref_stop; ++memref) {
|
||||
if (memref->address == address && memref->value.size == size)
|
||||
return memref;
|
||||
}
|
||||
|
||||
if (!memref_list->next)
|
||||
break;
|
||||
|
||||
memref_list = memref_list->next;
|
||||
} while (1);
|
||||
}
|
||||
else {
|
||||
/* indirect references always create a new entry because we can't guarantee that the
|
||||
* indirection amount will be the same between references. because they aren't shared,
|
||||
* don't bother putting them in the chain.
|
||||
*/
|
||||
memref = RC_ALLOC(rc_memref_t, parse);
|
||||
|
||||
/* no match found, find a place to put the new entry */
|
||||
memref_list = &parse->memrefs->memrefs;
|
||||
while (memref_list->count == memref_list->capacity && memref_list->next)
|
||||
memref_list = memref_list->next;
|
||||
|
||||
/* create a new entry */
|
||||
if (memref_list->count < memref_list->capacity) {
|
||||
memref = &memref_list->items[memref_list->count++];
|
||||
} else {
|
||||
const int32_t old_offset = parse->offset;
|
||||
|
||||
if (memref_list->capacity != 0) {
|
||||
memref_list = memref_list->next = RC_ALLOC_SCRATCH(rc_memref_list_t, parse);
|
||||
memref_list->next = NULL;
|
||||
}
|
||||
|
||||
memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_memref_t, 8, parse);
|
||||
memref_list->count = 1;
|
||||
memref_list->capacity = 8;
|
||||
memref_list->allocated = 0;
|
||||
|
||||
memref = memref_list->items;
|
||||
|
||||
/* in preparse mode, don't count this memory, we'll do a single allocation once we have
|
||||
* the final total */
|
||||
if (!parse->buffer)
|
||||
parse->offset = old_offset;
|
||||
}
|
||||
|
||||
memset(memref, 0, sizeof(*memref));
|
||||
memref->address = address;
|
||||
memref->value.memref_type = RC_MEMREF_TYPE_MEMREF;
|
||||
memref->value.type = RC_VALUE_TYPE_UNSIGNED;
|
||||
memref->value.size = size;
|
||||
memref->value.is_indirect = is_indirect;
|
||||
memref->address = address;
|
||||
|
||||
return memref;
|
||||
}
|
||||
|
||||
rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent,
|
||||
uint8_t modifier_type, const rc_operand_t* modifier) {
|
||||
rc_modified_memref_list_t* modified_memref_list = NULL;
|
||||
rc_modified_memref_t* modified_memref = NULL;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (i == 0) {
|
||||
if (!parse->existing_memrefs)
|
||||
continue;
|
||||
|
||||
modified_memref_list = &parse->existing_memrefs->modified_memrefs;
|
||||
}
|
||||
else {
|
||||
modified_memref_list = &parse->memrefs->modified_memrefs;
|
||||
}
|
||||
|
||||
do {
|
||||
const rc_modified_memref_t* memref_stop;
|
||||
|
||||
modified_memref = modified_memref_list->items;
|
||||
memref_stop = modified_memref + modified_memref_list->count;
|
||||
|
||||
for (; modified_memref < memref_stop; ++modified_memref) {
|
||||
if (modified_memref->memref.value.size == size &&
|
||||
modified_memref->modifier_type == modifier_type &&
|
||||
rc_operands_are_equal(&modified_memref->parent, parent) &&
|
||||
rc_operands_are_equal(&modified_memref->modifier, modifier)) {
|
||||
return modified_memref;
|
||||
}
|
||||
}
|
||||
|
||||
if (!modified_memref_list->next)
|
||||
break;
|
||||
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* no match found, find a place to put the new entry */
|
||||
modified_memref_list = &parse->memrefs->modified_memrefs;
|
||||
while (modified_memref_list->count == modified_memref_list->capacity && modified_memref_list->next)
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
|
||||
/* create a new entry */
|
||||
if (modified_memref_list->count < modified_memref_list->capacity) {
|
||||
modified_memref = &modified_memref_list->items[modified_memref_list->count++];
|
||||
} else {
|
||||
const int32_t old_offset = parse->offset;
|
||||
|
||||
if (modified_memref_list->capacity != 0) {
|
||||
modified_memref_list = modified_memref_list->next = RC_ALLOC_SCRATCH(rc_modified_memref_list_t, parse);
|
||||
modified_memref_list->next = NULL;
|
||||
}
|
||||
|
||||
modified_memref_list->items = RC_ALLOC_ARRAY_SCRATCH(rc_modified_memref_t, 8, parse);
|
||||
modified_memref_list->count = 1;
|
||||
modified_memref_list->capacity = 8;
|
||||
modified_memref_list->allocated = 0;
|
||||
|
||||
modified_memref = modified_memref_list->items;
|
||||
|
||||
/* in preparse mode, don't count this memory, we'll do a single allocation once we have
|
||||
* the final total */
|
||||
if (!parse->buffer)
|
||||
parse->offset = old_offset;
|
||||
}
|
||||
|
||||
memset(modified_memref, 0, sizeof(*modified_memref));
|
||||
modified_memref->memref.value.memref_type = RC_MEMREF_TYPE_MODIFIED_MEMREF;
|
||||
modified_memref->memref.value.size = size;
|
||||
modified_memref->memref.value.type = (size == RC_MEMSIZE_FLOAT) ? RC_VALUE_TYPE_FLOAT : RC_VALUE_TYPE_UNSIGNED;
|
||||
memcpy(&modified_memref->parent, parent, sizeof(modified_memref->parent));
|
||||
memcpy(&modified_memref->modifier, modifier, sizeof(modified_memref->modifier));
|
||||
modified_memref->modifier_type = modifier_type;
|
||||
modified_memref->memref.address = rc_operand_is_memref(modifier) ? modifier->value.memref->address : modifier->value.num;
|
||||
|
||||
return modified_memref;
|
||||
}
|
||||
|
||||
void rc_memrefs_init(rc_memrefs_t* memrefs)
|
||||
{
|
||||
memset(memrefs, 0, sizeof(*memrefs));
|
||||
|
||||
memrefs->memrefs.capacity = 32;
|
||||
memrefs->memrefs.items =
|
||||
(rc_memref_t*)malloc(memrefs->memrefs.capacity * sizeof(rc_memref_t));
|
||||
memrefs->memrefs.allocated = 1;
|
||||
|
||||
memrefs->modified_memrefs.capacity = 16;
|
||||
memrefs->modified_memrefs.items =
|
||||
(rc_modified_memref_t*)malloc(memrefs->modified_memrefs.capacity * sizeof(rc_modified_memref_t));
|
||||
memrefs->modified_memrefs.allocated = 1;
|
||||
}
|
||||
|
||||
void rc_memrefs_destroy(rc_memrefs_t* memrefs)
|
||||
{
|
||||
rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
||||
|
||||
do {
|
||||
rc_memref_list_t* current_memref_list = memref_list;
|
||||
memref_list = memref_list->next;
|
||||
|
||||
if (current_memref_list->allocated) {
|
||||
if (current_memref_list->items)
|
||||
free(current_memref_list->items);
|
||||
|
||||
if (current_memref_list != &memrefs->memrefs)
|
||||
free(current_memref_list);
|
||||
}
|
||||
} while (memref_list);
|
||||
|
||||
do {
|
||||
rc_modified_memref_list_t* current_modified_memref_list = modified_memref_list;
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
|
||||
if (current_modified_memref_list->allocated) {
|
||||
if (current_modified_memref_list->items)
|
||||
free(current_modified_memref_list->items);
|
||||
|
||||
if (current_modified_memref_list != &memrefs->modified_memrefs)
|
||||
free(current_modified_memref_list);
|
||||
}
|
||||
} while (modified_memref_list);
|
||||
|
||||
free(memrefs);
|
||||
}
|
||||
|
||||
uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
while (memref_list) {
|
||||
count += memref_list->count;
|
||||
memref_list = memref_list->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
const rc_modified_memref_list_t* modified_memref_list = &memrefs->modified_memrefs;
|
||||
while (modified_memref_list) {
|
||||
count += modified_memref_list->count;
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) {
|
||||
const char* aux = *memaddr;
|
||||
char* end;
|
||||
@@ -77,7 +268,12 @@ int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address) {
|
||||
/* case 'y': case 'Y': 64 bit? */
|
||||
/* case 'z': case 'Z': 128 bit? */
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '0':
|
||||
if (*aux == 'x') /* user mistyped an extra 0x: 0x0xabcd */
|
||||
return RC_INVALID_MEMORY_OPERAND;
|
||||
/* fallthrough */
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
||||
@@ -485,19 +681,12 @@ void rc_update_memref_value(rc_memref_value_t* memref, uint32_t new_value) {
|
||||
}
|
||||
}
|
||||
|
||||
void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud) {
|
||||
while (memref) {
|
||||
/* indirect memory references are not shared and will be updated in rc_get_memref_value */
|
||||
if (!memref->value.is_indirect)
|
||||
rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud));
|
||||
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs)
|
||||
{
|
||||
if (memrefs)
|
||||
memset(memrefs, 0, sizeof(*memrefs));
|
||||
|
||||
memref = memref->next;
|
||||
}
|
||||
}
|
||||
|
||||
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs) {
|
||||
parse->first_memref = memrefs;
|
||||
*memrefs = 0;
|
||||
parse->memrefs = memrefs;
|
||||
}
|
||||
|
||||
static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int operand_type) {
|
||||
@@ -520,12 +709,68 @@ static uint32_t rc_get_memref_value_value(const rc_memref_value_t* memref, int o
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state) {
|
||||
/* if this is an indirect reference, handle the indirection. */
|
||||
if (memref->value.is_indirect) {
|
||||
const uint32_t new_address = memref->address + eval_state->add_address;
|
||||
rc_update_memref_value(&memref->value, rc_peek_value(new_address, memref->value.size, eval_state->peek, eval_state->peek_userdata));
|
||||
void rc_get_memref_value(rc_typed_value_t* value, rc_memref_t* memref, int operand_type) {
|
||||
value->type = memref->value.type;
|
||||
value->value.u32 = rc_get_memref_value_value(&memref->value, operand_type);
|
||||
}
|
||||
|
||||
uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_peek_t peek, void* ud) {
|
||||
rc_typed_value_t value, modifier;
|
||||
|
||||
rc_evaluate_operand(&value, &memref->parent, NULL);
|
||||
rc_evaluate_operand(&modifier, &memref->modifier, NULL);
|
||||
|
||||
switch (memref->modifier_type) {
|
||||
case RC_OPERATOR_INDIRECT_READ:
|
||||
rc_typed_value_add(&value, &modifier);
|
||||
rc_typed_value_convert(&value, RC_VALUE_TYPE_UNSIGNED);
|
||||
value.value.u32 = rc_peek_value(value.value.u32, memref->memref.value.size, peek, ud);
|
||||
value.type = memref->memref.value.type;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_SUB_PARENT:
|
||||
rc_typed_value_negate(&value);
|
||||
rc_typed_value_add(&value, &modifier);
|
||||
rc_typed_value_convert(&value, memref->memref.value.type);
|
||||
break;
|
||||
|
||||
default:
|
||||
rc_typed_value_combine(&value, &modifier, memref->modifier_type);
|
||||
rc_typed_value_convert(&value, memref->memref.value.type);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc_get_memref_value_value(&memref->value, operand_type);
|
||||
return value.value.u32;
|
||||
}
|
||||
|
||||
void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud) {
|
||||
rc_memref_list_t* memref_list;
|
||||
rc_modified_memref_list_t* modified_memref_list;
|
||||
|
||||
memref_list = &memrefs->memrefs;
|
||||
do
|
||||
{
|
||||
rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_stop = memref + memref_list->count;
|
||||
|
||||
for (; memref < memref_stop; ++memref) {
|
||||
if (memref->value.type != RC_VALUE_TYPE_NONE)
|
||||
rc_update_memref_value(&memref->value, rc_peek_value(memref->address, memref->value.size, peek, ud));
|
||||
}
|
||||
|
||||
memref_list = memref_list->next;
|
||||
} while (memref_list);
|
||||
|
||||
modified_memref_list = &memrefs->modified_memrefs;
|
||||
if (modified_memref_list->count) {
|
||||
do {
|
||||
rc_modified_memref_t* modified_memref = modified_memref_list->items;
|
||||
const rc_modified_memref_t* modified_memref_stop = modified_memref + modified_memref_list->count;
|
||||
|
||||
for (; modified_memref < modified_memref_stop; ++modified_memref)
|
||||
rc_update_memref_value(&modified_memref->memref.value, rc_get_modified_memref_value(modified_memref, peek, ud));
|
||||
|
||||
modified_memref_list = modified_memref_list->next;
|
||||
} while (modified_memref_list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,11 +61,13 @@ static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, rc_par
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
|
||||
self->type = RC_OPERAND_LUA;
|
||||
self->size = RC_MEMSIZE_32_BITS;
|
||||
self->memref_access_type = RC_OPERAND_ADDRESS;
|
||||
*memaddr = aux;
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr) {
|
||||
static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
const char* aux = *memaddr;
|
||||
size_t i;
|
||||
char varName[RC_VALUE_MAX_NAME_LENGTH + 1] = { 0 };
|
||||
@@ -86,6 +88,15 @@ static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr) {
|
||||
++aux;
|
||||
|
||||
if (strcmp(varName, "recall") == 0) {
|
||||
if (parse->remember.type == RC_OPERAND_NONE) {
|
||||
self->value.memref = NULL;
|
||||
self->size = RC_MEMSIZE_32_BITS;
|
||||
self->memref_access_type = RC_OPERAND_ADDRESS;
|
||||
}
|
||||
else {
|
||||
memcpy(self, &parse->remember, sizeof(*self));
|
||||
self->memref_access_type = self->type;
|
||||
}
|
||||
self->type = RC_OPERAND_RECALL;
|
||||
}
|
||||
else { /* process named variable when feature is available.*/
|
||||
@@ -96,7 +107,7 @@ static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr) {
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect) {
|
||||
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
const char* aux = *memaddr;
|
||||
uint32_t address;
|
||||
uint8_t size;
|
||||
@@ -128,6 +139,8 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
|
||||
break;
|
||||
}
|
||||
|
||||
self->memref_access_type = self->type;
|
||||
|
||||
ret = rc_parse_memref(&aux, &self->size, &address);
|
||||
if (ret != RC_OK)
|
||||
return ret;
|
||||
@@ -137,13 +150,28 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
|
||||
/* if the shared size differs from the requested size and it's a prior operation, we
|
||||
* have to check to make sure both sizes use the same mask, or the prior value may be
|
||||
* updated when bits outside the mask are modified, which would make it look like the
|
||||
* current value once the mask is applied. if the mask differs, create a new
|
||||
* current value once the mask is applied. if the mask differs, create a new
|
||||
* non-shared record for tracking the prior data. */
|
||||
if (rc_memref_mask(size) != rc_memref_mask(self->size))
|
||||
size = self->size;
|
||||
}
|
||||
|
||||
self->value.memref = rc_alloc_memref(parse, address, size, is_indirect);
|
||||
if (parse->indirect_parent.type != RC_OPERAND_NONE) {
|
||||
if (parse->indirect_parent.type == RC_OPERAND_CONST) {
|
||||
self->value.memref = rc_alloc_memref(parse, address + parse->indirect_parent.value.num, size);
|
||||
}
|
||||
else {
|
||||
rc_operand_t offset;
|
||||
rc_operand_set_const(&offset, address);
|
||||
|
||||
self->value.memref = (rc_memref_t*)rc_alloc_modified_memref(parse,
|
||||
size, &parse->indirect_parent, RC_OPERATOR_INDIRECT_READ, &offset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
self->value.memref = rc_alloc_memref(parse, address, size);
|
||||
}
|
||||
|
||||
if (parse->offset < 0)
|
||||
return parse->offset;
|
||||
|
||||
@@ -151,7 +179,7 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indirect, rc_parse_state_t* parse) {
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
const char* aux = *memaddr;
|
||||
char* end;
|
||||
int ret;
|
||||
@@ -159,8 +187,6 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
int negative;
|
||||
int allow_decimal = 0;
|
||||
|
||||
self->size = RC_MEMSIZE_32_BITS;
|
||||
|
||||
switch (*aux) {
|
||||
case 'h': case 'H': /* hex constant */
|
||||
if (aux[2] == 'x' || aux[2] == 'X') {
|
||||
@@ -175,15 +201,14 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
if (value > 0xffffffffU)
|
||||
value = 0xffffffffU;
|
||||
|
||||
self->type = RC_OPERAND_CONST;
|
||||
self->value.num = (unsigned)value;
|
||||
rc_operand_set_const(self, (unsigned)value);
|
||||
|
||||
aux = end;
|
||||
break;
|
||||
|
||||
case 'f': case 'F': /* floating point constant */
|
||||
if (isalpha((unsigned char)aux[1])) {
|
||||
ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
|
||||
ret = rc_parse_operand_memory(self, &aux, parse);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -211,6 +236,7 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
/* custom parser for decimal values to ignore locale */
|
||||
unsigned long shift = 1;
|
||||
unsigned long fraction = 0;
|
||||
double dbl_val;
|
||||
|
||||
aux = end + 1;
|
||||
if (*aux < '0' || *aux > '9')
|
||||
@@ -231,19 +257,19 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
/* non-zero fractional part, convert to double and merge in integer portion */
|
||||
const double dbl_fraction = ((double)fraction) / ((double)shift);
|
||||
if (negative)
|
||||
self->value.dbl = ((double)(-((long)value))) - dbl_fraction;
|
||||
dbl_val = ((double)(-((long)value))) - dbl_fraction;
|
||||
else
|
||||
self->value.dbl = (double)value + dbl_fraction;
|
||||
dbl_val = (double)value + dbl_fraction;
|
||||
}
|
||||
else {
|
||||
/* fractional part is 0, just convert the integer portion */
|
||||
if (negative)
|
||||
self->value.dbl = (double)(-((long)value));
|
||||
dbl_val = (double)(-((long)value));
|
||||
else
|
||||
self->value.dbl = (double)value;
|
||||
dbl_val = (double)value;
|
||||
}
|
||||
|
||||
self->type = RC_OPERAND_FP;
|
||||
rc_operand_set_float_const(self, dbl_val);
|
||||
}
|
||||
else {
|
||||
/* not a floating point value, make sure something was read and advance the read pointer */
|
||||
@@ -255,17 +281,15 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
if (value > 0x7fffffffU)
|
||||
value = 0x7fffffffU;
|
||||
|
||||
self->type = RC_OPERAND_CONST;
|
||||
|
||||
if (negative)
|
||||
self->value.num = (unsigned)(-((long)value));
|
||||
rc_operand_set_const(self, (unsigned)(-((long)value)));
|
||||
else
|
||||
self->value.num = (unsigned)value;
|
||||
rc_operand_set_const(self, (unsigned)value);
|
||||
}
|
||||
break;
|
||||
case '{': /* variable */
|
||||
++aux;
|
||||
ret = rc_parse_operand_variable(self, &aux);
|
||||
ret = rc_parse_operand_variable(self, &aux, parse);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -275,7 +299,7 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
if (aux[1] == 'x' || aux[1] == 'X') { /* hex integer constant */
|
||||
/* fallthrough */ /* to default */
|
||||
default:
|
||||
ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
|
||||
ret = rc_parse_operand_memory(self, &aux, parse);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -292,8 +316,7 @@ int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indire
|
||||
if (value > 0xffffffffU)
|
||||
value = 0xffffffffU;
|
||||
|
||||
self->type = RC_OPERAND_CONST;
|
||||
self->value.num = (unsigned)value;
|
||||
rc_operand_set_const(self, (unsigned)value);
|
||||
|
||||
aux = end;
|
||||
break;
|
||||
@@ -332,8 +355,74 @@ static int rc_luapeek(lua_State* L) {
|
||||
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
|
||||
int rc_operand_is_float_memref(const rc_operand_t* self) {
|
||||
switch (self->size) {
|
||||
void rc_operand_set_const(rc_operand_t* self, uint32_t value) {
|
||||
self->size = RC_MEMSIZE_32_BITS;
|
||||
self->type = RC_OPERAND_CONST;
|
||||
self->memref_access_type = RC_OPERAND_NONE;
|
||||
self->value.num = value;
|
||||
}
|
||||
|
||||
void rc_operand_set_float_const(rc_operand_t* self, double value) {
|
||||
self->size = RC_MEMSIZE_FLOAT;
|
||||
self->type = RC_OPERAND_FP;
|
||||
self->memref_access_type = RC_OPERAND_NONE;
|
||||
self->value.dbl = value;
|
||||
}
|
||||
|
||||
int rc_operands_are_equal(const rc_operand_t* left, const rc_operand_t* right) {
|
||||
if (left->type != right->type)
|
||||
return 0;
|
||||
|
||||
switch (left->type) {
|
||||
case RC_OPERAND_CONST:
|
||||
return (left->value.num == right->value.num);
|
||||
case RC_OPERAND_FP:
|
||||
return (left->value.dbl == right->value.dbl);
|
||||
case RC_OPERAND_RECALL:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* comparing two memrefs - look for exact matches on type and size */
|
||||
if (left->size != right->size || left->value.memref->value.memref_type != right->value.memref->value.memref_type)
|
||||
return 0;
|
||||
|
||||
switch (left->value.memref->value.memref_type) {
|
||||
case RC_MEMREF_TYPE_MODIFIED_MEMREF:
|
||||
{
|
||||
const rc_modified_memref_t* left_memref = (const rc_modified_memref_t*)left->value.memref;
|
||||
const rc_modified_memref_t* right_memref = (const rc_modified_memref_t*)right->value.memref;
|
||||
return (left_memref->modifier_type == right_memref->modifier_type &&
|
||||
rc_operands_are_equal(&left_memref->parent, &right_memref->parent) &&
|
||||
rc_operands_are_equal(&left_memref->modifier, &right_memref->modifier));
|
||||
}
|
||||
|
||||
default:
|
||||
return (left->value.memref->address == right->value.memref->address &&
|
||||
left->value.memref->value.size == right->value.memref->value.size);
|
||||
}
|
||||
}
|
||||
|
||||
int rc_operator_is_modifying(int oper) {
|
||||
switch (oper) {
|
||||
case RC_OPERATOR_AND:
|
||||
case RC_OPERATOR_XOR:
|
||||
case RC_OPERATOR_DIV:
|
||||
case RC_OPERATOR_MULT:
|
||||
case RC_OPERATOR_MOD:
|
||||
case RC_OPERATOR_ADD:
|
||||
case RC_OPERATOR_SUB:
|
||||
case RC_OPERATOR_NONE: /* NONE operator implies "* 1" */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rc_memsize_is_float(uint8_t size) {
|
||||
switch (size) {
|
||||
case RC_MEMSIZE_FLOAT:
|
||||
case RC_MEMSIZE_FLOAT_BE:
|
||||
case RC_MEMSIZE_DOUBLE32:
|
||||
@@ -347,8 +436,24 @@ int rc_operand_is_float_memref(const rc_operand_t* self) {
|
||||
}
|
||||
}
|
||||
|
||||
int rc_operand_is_memref(const rc_operand_t* self) {
|
||||
switch (self->type) {
|
||||
int rc_operand_is_float_memref(const rc_operand_t* self) {
|
||||
if (!rc_operand_is_memref(self))
|
||||
return 0;
|
||||
|
||||
if (self->type == RC_OPERAND_RECALL)
|
||||
return rc_memsize_is_float(self->memref_access_type);
|
||||
|
||||
if (self->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
||||
const rc_modified_memref_t* memref = (const rc_modified_memref_t*)self->value.memref;
|
||||
if (memref->modifier_type != RC_OPERATOR_INDIRECT_READ)
|
||||
return rc_memsize_is_float(self->value.memref->value.size);
|
||||
}
|
||||
|
||||
return rc_memsize_is_float(self->size);
|
||||
}
|
||||
|
||||
int rc_operand_type_is_memref(uint8_t type) {
|
||||
switch (type) {
|
||||
case RC_OPERAND_CONST:
|
||||
case RC_OPERAND_FP:
|
||||
case RC_OPERAND_LUA:
|
||||
@@ -360,6 +465,10 @@ int rc_operand_is_memref(const rc_operand_t* self) {
|
||||
}
|
||||
}
|
||||
|
||||
int rc_operand_is_memref(const rc_operand_t* self) {
|
||||
return rc_operand_type_is_memref(self->type);
|
||||
}
|
||||
|
||||
int rc_operand_is_recall(const rc_operand_t* self) {
|
||||
switch (self->type) {
|
||||
case RC_OPERAND_RECALL:
|
||||
@@ -377,7 +486,7 @@ int rc_operand_is_float(const rc_operand_t* self) {
|
||||
return rc_operand_is_float_memref(self);
|
||||
}
|
||||
|
||||
uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) {
|
||||
static uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) {
|
||||
switch (self->type)
|
||||
{
|
||||
case RC_OPERAND_BCD:
|
||||
@@ -465,7 +574,44 @@ uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) {
|
||||
return value;
|
||||
}
|
||||
|
||||
void rc_evaluate_operand(rc_typed_value_t* result, rc_operand_t* self, rc_eval_state_t* eval_state) {
|
||||
void rc_operand_addsource(rc_operand_t* self, rc_parse_state_t* parse, uint8_t new_size) {
|
||||
rc_modified_memref_t* modified_memref;
|
||||
|
||||
if (rc_operand_is_memref(&parse->addsource_parent)) {
|
||||
rc_operand_t modifier;
|
||||
|
||||
if ((self->type == RC_OPERAND_DELTA || self->type == RC_OPERAND_PRIOR) &&
|
||||
self->type == parse->addsource_parent.type) {
|
||||
/* if adding prev(x) and prev(y), just add x and y and take the prev of that */
|
||||
memcpy(&modifier, self, sizeof(modifier));
|
||||
modifier.type = parse->addsource_parent.type = RC_OPERAND_ADDRESS;
|
||||
|
||||
modified_memref = rc_alloc_modified_memref(parse,
|
||||
new_size, &parse->addsource_parent, parse->addsource_oper, &modifier);
|
||||
}
|
||||
else {
|
||||
modified_memref = rc_alloc_modified_memref(parse,
|
||||
new_size, &parse->addsource_parent, parse->addsource_oper, self);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* N + A => A + N */
|
||||
/* -N + A => A - N */
|
||||
modified_memref = rc_alloc_modified_memref(parse,
|
||||
new_size, &parse->addsource_parent, parse->addsource_oper, self);
|
||||
}
|
||||
|
||||
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))
|
||||
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;
|
||||
}
|
||||
|
||||
void rc_evaluate_operand(rc_typed_value_t* result, const rc_operand_t* self, rc_eval_state_t* eval_state) {
|
||||
#ifndef RC_DISABLE_LUA
|
||||
rc_luapeek_t luapeek;
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
@@ -510,16 +656,28 @@ void rc_evaluate_operand(rc_typed_value_t* result, rc_operand_t* self, rc_eval_s
|
||||
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
|
||||
break;
|
||||
|
||||
case RC_OPERAND_RECALL:
|
||||
result->type = eval_state->recall_value.type;
|
||||
result->value = eval_state->recall_value.value;
|
||||
return;
|
||||
|
||||
case RC_OPERAND_RECALL:
|
||||
if (!rc_operand_type_is_memref(self->memref_access_type)) {
|
||||
rc_operand_t recall;
|
||||
memcpy(&recall, self, sizeof(recall));
|
||||
recall.type = self->memref_access_type;
|
||||
rc_evaluate_operand(result, &recall, eval_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->value.memref) {
|
||||
result->type = RC_VALUE_TYPE_UNSIGNED;
|
||||
result->value.u32 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
rc_get_memref_value(result, self->value.memref, self->memref_access_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
result->type = RC_VALUE_TYPE_UNSIGNED;
|
||||
result->value.u32 = rc_get_memref_value(self->value.memref, self->type, eval_state);
|
||||
rc_get_memref_value(result, self->value.memref, self->type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,27 +13,115 @@ typedef struct rc_scratch_string {
|
||||
}
|
||||
rc_scratch_string_t;
|
||||
|
||||
#define RC_ALLOW_ALIGN(T) struct __align_ ## T { char ch; T t; };
|
||||
typedef struct rc_modified_memref_t {
|
||||
rc_memref_t memref; /* for compatibility with rc_operand_t.value.memref */
|
||||
rc_operand_t parent; /* The parent memref this memref is derived from (type will always be a memref type) */
|
||||
rc_operand_t modifier; /* The modifier to apply to the parent. */
|
||||
uint8_t modifier_type; /* How to apply the modifier to the parent. (RC_OPERATOR_*) */
|
||||
}
|
||||
rc_modified_memref_t;
|
||||
|
||||
typedef struct rc_memref_list_t {
|
||||
rc_memref_t* items;
|
||||
struct rc_memref_list_t* next;
|
||||
uint16_t count;
|
||||
uint16_t capacity;
|
||||
uint8_t allocated;
|
||||
} rc_memref_list_t;
|
||||
|
||||
typedef struct rc_modified_memref_list_t {
|
||||
rc_modified_memref_t* items;
|
||||
struct rc_modified_memref_list_t* next;
|
||||
uint16_t count;
|
||||
uint16_t capacity;
|
||||
uint8_t allocated;
|
||||
} rc_modified_memref_list_t;
|
||||
|
||||
typedef struct rc_memrefs_t {
|
||||
rc_memref_list_t memrefs;
|
||||
rc_modified_memref_list_t modified_memrefs;
|
||||
} rc_memrefs_t;
|
||||
|
||||
typedef struct rc_trigger_with_memrefs_t {
|
||||
rc_trigger_t trigger;
|
||||
rc_memrefs_t memrefs;
|
||||
} rc_trigger_with_memrefs_t;
|
||||
|
||||
typedef struct rc_lboard_with_memrefs_t {
|
||||
rc_lboard_t lboard;
|
||||
rc_memrefs_t memrefs;
|
||||
} rc_lboard_with_memrefs_t;
|
||||
|
||||
typedef struct rc_richpresence_with_memrefs_t {
|
||||
rc_richpresence_t richpresence;
|
||||
rc_memrefs_t memrefs;
|
||||
} rc_richpresence_with_memrefs_t;
|
||||
|
||||
typedef struct rc_value_with_memrefs_t {
|
||||
rc_value_t value;
|
||||
rc_memrefs_t memrefs;
|
||||
} rc_value_with_memrefs_t;
|
||||
|
||||
/* enum helpers for natvis expansion. Have to use a struct to define the mapping,
|
||||
* and a single field to allow the conditional logic to switch on the value */
|
||||
typedef struct __rc_bool_enum_t { uint8_t value; } __rc_bool_enum_t;
|
||||
typedef struct __rc_memsize_enum_t { uint8_t value; } __rc_memsize_enum_t;
|
||||
typedef struct __rc_memsize_enum_func_t { uint8_t value; } __rc_memsize_enum_func_t;
|
||||
typedef struct __rc_operand_enum_t { uint8_t value; } __rc_operand_enum_t;
|
||||
typedef struct __rc_value_type_enum_t { uint8_t value; } __rc_value_type_enum_t;
|
||||
typedef struct __rc_memref_type_enum_t { uint8_t value; } __rc_memref_type_enum_t;
|
||||
typedef struct __rc_condition_enum_t { uint8_t value; } __rc_condition_enum_t;
|
||||
typedef struct __rc_condition_enum_str_t { uint8_t value; } __rc_condition_enum_str_t;
|
||||
typedef struct __rc_condset_list_t { rc_condset_t* first_condset; } __rc_condset_list_t;
|
||||
typedef struct __rc_operator_enum_t { uint8_t value; } __rc_operator_enum_t;
|
||||
typedef struct __rc_operator_enum_str_t { uint8_t value; } __rc_operator_enum_str_t;
|
||||
typedef struct __rc_operand_memref_t { rc_operand_t operand; } __rc_operand_memref_t; /* requires &rc_operand_t to be the same as &rc_operand_t.value.memref */
|
||||
typedef struct __rc_value_list_t { rc_value_t* first_value; } __rc_value_list_t;
|
||||
typedef struct __rc_trigger_state_enum_t { uint8_t value; } __rc_trigger_state_enum_t;
|
||||
typedef struct __rc_lboard_state_enum_t { uint8_t value; } __rc_lboard_state_enum_t;
|
||||
typedef struct __rc_richpresence_display_list_t { rc_richpresence_display_t* first_display; } __rc_richpresence_display_list_t;
|
||||
typedef struct __rc_richpresence_display_part_list_t { rc_richpresence_display_part_t* display; } __rc_richpresence_display_part_list_t;
|
||||
typedef struct __rc_richpresence_lookup_list_t { rc_richpresence_lookup_t* first_lookup; } __rc_richpresence_lookup_list_t;
|
||||
typedef struct __rc_format_enum_t { uint8_t value; } __rc_format_enum_t;
|
||||
|
||||
#define RC_ALLOW_ALIGN(T) struct __align_ ## T { uint8_t ch; T t; };
|
||||
|
||||
RC_ALLOW_ALIGN(rc_condition_t)
|
||||
RC_ALLOW_ALIGN(rc_condset_t)
|
||||
RC_ALLOW_ALIGN(rc_modified_memref_t)
|
||||
RC_ALLOW_ALIGN(rc_lboard_t)
|
||||
RC_ALLOW_ALIGN(rc_lboard_with_memrefs_t)
|
||||
RC_ALLOW_ALIGN(rc_memref_t)
|
||||
RC_ALLOW_ALIGN(rc_memref_list_t)
|
||||
RC_ALLOW_ALIGN(rc_memrefs_t)
|
||||
RC_ALLOW_ALIGN(rc_modified_memref_list_t)
|
||||
RC_ALLOW_ALIGN(rc_operand_t)
|
||||
RC_ALLOW_ALIGN(rc_richpresence_t)
|
||||
RC_ALLOW_ALIGN(rc_richpresence_display_t)
|
||||
RC_ALLOW_ALIGN(rc_richpresence_display_part_t)
|
||||
RC_ALLOW_ALIGN(rc_richpresence_lookup_t)
|
||||
RC_ALLOW_ALIGN(rc_richpresence_lookup_item_t)
|
||||
RC_ALLOW_ALIGN(rc_richpresence_with_memrefs_t)
|
||||
RC_ALLOW_ALIGN(rc_scratch_string_t)
|
||||
RC_ALLOW_ALIGN(rc_trigger_t)
|
||||
RC_ALLOW_ALIGN(rc_trigger_with_memrefs_t)
|
||||
RC_ALLOW_ALIGN(rc_value_t)
|
||||
RC_ALLOW_ALIGN(rc_value_with_memrefs_t)
|
||||
RC_ALLOW_ALIGN(char)
|
||||
|
||||
#define RC_ALIGNOF(T) (sizeof(struct __align_ ## T) - sizeof(T))
|
||||
#define RC_OFFSETOF(o, t) (int)((char*)&(o.t) - (char*)&(o))
|
||||
#define RC_OFFSETOF(o, t) (int)((uint8_t*)&(o.t) - (uint8_t*)&(o))
|
||||
|
||||
#define RC_ALLOC(t, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t)))
|
||||
#define RC_ALLOC_SCRATCH(t, p) ((t*)rc_alloc_scratch((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t)))
|
||||
#define RC_ALLOC_ARRAY(t, n, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, (n) * sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t)))
|
||||
#define RC_ALLOC_ARRAY_SCRATCH(t, n, p) ((t*)rc_alloc_scratch((p)->buffer, &(p)->offset, (n) * sizeof(t), RC_ALIGNOF(t), &(p)->scratch, RC_OFFSETOF((p)->scratch.objs, __ ## t)))
|
||||
|
||||
#define RC_ALLOC_WITH_TRAILING(container_type, trailing_type, trailing_field, trailing_count, parse) ((container_type*)rc_alloc(\
|
||||
(parse)->buffer, &(parse)->offset, \
|
||||
RC_OFFSETOF((*(container_type*)NULL),trailing_field) + trailing_count * sizeof(trailing_type), \
|
||||
RC_ALIGNOF(container_type), &(parse)->scratch, 0))
|
||||
#define RC_GET_TRAILING(container_pointer, container_type, trailing_type, trailing_field) (trailing_type*)(&((container_type*)(container_pointer))->trailing_field)
|
||||
|
||||
/* force alignment to 4 bytes on 32-bit systems, or 8 bytes on 64-bit systems */
|
||||
#define RC_ALIGN(n) (((n) + (sizeof(void*)-1)) & ~(sizeof(void*)-1))
|
||||
@@ -45,17 +133,49 @@ typedef struct {
|
||||
struct objs {
|
||||
rc_condition_t* __rc_condition_t;
|
||||
rc_condset_t* __rc_condset_t;
|
||||
rc_modified_memref_t* __rc_modified_memref_t;
|
||||
rc_lboard_t* __rc_lboard_t;
|
||||
rc_lboard_with_memrefs_t* __rc_lboard_with_memrefs_t;
|
||||
rc_memref_t* __rc_memref_t;
|
||||
rc_memref_list_t* __rc_memref_list_t;
|
||||
rc_memrefs_t* __rc_memrefs_t;
|
||||
rc_modified_memref_list_t* __rc_modified_memref_list_t;
|
||||
rc_operand_t* __rc_operand_t;
|
||||
rc_richpresence_t* __rc_richpresence_t;
|
||||
rc_richpresence_display_t* __rc_richpresence_display_t;
|
||||
rc_richpresence_display_part_t* __rc_richpresence_display_part_t;
|
||||
rc_richpresence_lookup_t* __rc_richpresence_lookup_t;
|
||||
rc_richpresence_lookup_item_t* __rc_richpresence_lookup_item_t;
|
||||
rc_richpresence_with_memrefs_t* __rc_richpresence_with_memrefs_t;
|
||||
rc_scratch_string_t __rc_scratch_string_t;
|
||||
rc_trigger_t* __rc_trigger_t;
|
||||
rc_trigger_with_memrefs_t* __rc_trigger_with_memrefs_t;
|
||||
rc_value_t* __rc_value_t;
|
||||
rc_value_with_memrefs_t* __rc_value_with_memrefs_t;
|
||||
|
||||
/* these fields aren't actually used by the code, but they force the
|
||||
* virtual enum wrapper types to exist so natvis can use them */
|
||||
union {
|
||||
__rc_bool_enum_t boolean;
|
||||
__rc_memsize_enum_t memsize;
|
||||
__rc_memsize_enum_func_t memsize_func;
|
||||
__rc_operand_enum_t operand;
|
||||
__rc_value_type_enum_t value_type;
|
||||
__rc_memref_type_enum_t memref_type;
|
||||
__rc_condition_enum_t condition;
|
||||
__rc_condition_enum_str_t condition_str;
|
||||
__rc_condset_list_t condset_list;
|
||||
__rc_operator_enum_t oper;
|
||||
__rc_operator_enum_str_t oper_str;
|
||||
__rc_operand_memref_t operand_memref;
|
||||
__rc_value_list_t value_list;
|
||||
__rc_trigger_state_enum_t trigger_state;
|
||||
__rc_lboard_state_enum_t lboard_state;
|
||||
__rc_richpresence_display_list_t richpresence_display_list;
|
||||
__rc_richpresence_display_part_list_t richpresence_display_part_list;
|
||||
__rc_richpresence_lookup_list_t richpresence_lookup_list;
|
||||
__rc_format_enum_t format;
|
||||
} natvis_extension;
|
||||
} objs;
|
||||
}
|
||||
rc_scratch_t;
|
||||
@@ -78,72 +198,128 @@ typedef struct {
|
||||
}
|
||||
rc_typed_value_t;
|
||||
|
||||
enum {
|
||||
RC_MEMREF_TYPE_MEMREF, /* rc_memref_t */
|
||||
RC_MEMREF_TYPE_MODIFIED_MEMREF, /* rc_modified_memref_t */
|
||||
RC_MEMREF_TYPE_VALUE /* rc_value_t */
|
||||
};
|
||||
|
||||
#define RC_MEASURED_UNKNOWN 0xFFFFFFFF
|
||||
#define RC_OPERAND_NONE 0xFF
|
||||
|
||||
typedef struct {
|
||||
rc_typed_value_t add_value;/* AddSource/SubSource */
|
||||
int32_t add_hits; /* AddHits */
|
||||
uint32_t add_address; /* AddAddress */
|
||||
|
||||
/* memory accessors */
|
||||
rc_peek_t peek;
|
||||
void* peek_userdata;
|
||||
#ifndef RC_DISABLE_LUA
|
||||
lua_State* L;
|
||||
#endif
|
||||
|
||||
rc_typed_value_t measured_value; /* Measured */
|
||||
rc_typed_value_t recall_value; /* Set by RC_CONDITION_REMEMBER */
|
||||
uint8_t was_reset; /* ResetIf triggered */
|
||||
uint8_t has_hits; /* one of more hit counts is non-zero */
|
||||
uint8_t primed; /* true if all non-Trigger conditions are true */
|
||||
/* processing state */
|
||||
rc_typed_value_t measured_value; /* captured Measured value */
|
||||
int32_t add_hits; /* AddHits/SubHits accumulator */
|
||||
uint8_t is_true; /* true if all conditions are true */
|
||||
uint8_t is_primed; /* true if all non-Trigger conditions are true */
|
||||
uint8_t is_paused; /* true if one or more PauseIf conditions is true */
|
||||
uint8_t can_measure; /* false if the measured value should be ignored */
|
||||
uint8_t measured_from_hits; /* true if the measured_value came from a condition's hit count */
|
||||
uint8_t was_cond_reset; /* ResetNextIf triggered */
|
||||
uint8_t and_next; /* true if the previous condition was AndNext true */
|
||||
uint8_t or_next; /* true if the previous condition was OrNext true */
|
||||
uint8_t reset_next; /* true if the previous condition was ResetNextIf true */
|
||||
uint8_t stop_processing; /* true to abort the processing loop */
|
||||
|
||||
/* result state */
|
||||
uint8_t has_hits; /* true if one of more hit counts is non-zero */
|
||||
uint8_t was_reset; /* true if one or more ResetIf conditions is true */
|
||||
uint8_t was_cond_reset; /* true if one or more ResetNextIf conditions is true */
|
||||
|
||||
/* control settings */
|
||||
uint8_t can_short_curcuit; /* allows logic processing to stop as soon as a false condition is encountered */
|
||||
}
|
||||
rc_eval_state_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t offset;
|
||||
|
||||
#ifndef RC_DISABLE_LUA
|
||||
lua_State* L;
|
||||
int funcs_ndx;
|
||||
#endif
|
||||
|
||||
void* buffer;
|
||||
rc_scratch_t scratch;
|
||||
|
||||
rc_memref_t** first_memref;
|
||||
rc_memrefs_t* memrefs;
|
||||
rc_memrefs_t* existing_memrefs;
|
||||
rc_value_t** variables;
|
||||
|
||||
uint32_t measured_target;
|
||||
int lines_read;
|
||||
|
||||
rc_operand_t addsource_parent;
|
||||
rc_operand_t indirect_parent;
|
||||
rc_operand_t remember;
|
||||
uint8_t addsource_oper;
|
||||
|
||||
uint8_t is_value;
|
||||
uint8_t has_required_hits;
|
||||
uint8_t measured_as_percent;
|
||||
}
|
||||
rc_parse_state_t;
|
||||
|
||||
typedef struct rc_preparse_state_t {
|
||||
rc_parse_state_t parse;
|
||||
rc_memrefs_t memrefs;
|
||||
} rc_preparse_state_t;
|
||||
|
||||
void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx);
|
||||
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_t** memrefs);
|
||||
void rc_init_parse_state_variables(rc_parse_state_t* parse, rc_value_t** variables);
|
||||
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs);
|
||||
void rc_reset_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, int funcs_ndx);
|
||||
void rc_destroy_parse_state(rc_parse_state_t* parse);
|
||||
void rc_init_preparse_state(rc_preparse_state_t* preparse, lua_State* L, int funcs_ndx);
|
||||
void rc_preparse_alloc_memrefs(rc_memrefs_t* memrefs, rc_preparse_state_t* preparse);
|
||||
void rc_preparse_reserve_memrefs(rc_preparse_state_t* preparse, rc_memrefs_t* memrefs);
|
||||
void rc_preparse_copy_memrefs(rc_parse_state_t* parse, rc_memrefs_t* memrefs);
|
||||
void rc_destroy_preparse_state(rc_preparse_state_t *preparse);
|
||||
void rc_copy_memrefs_into_parse_state(rc_parse_state_t* parse, rc_memref_t* memrefs);
|
||||
void rc_sync_operand(rc_operand_t* operand, rc_parse_state_t* parse, const rc_memref_t* memrefs);
|
||||
|
||||
void* rc_alloc(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset);
|
||||
void* rc_alloc_scratch(void* pointer, int32_t* offset, uint32_t size, uint32_t alignment, rc_scratch_t* scratch, uint32_t scratch_object_pointer_offset);
|
||||
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, size_t length);
|
||||
|
||||
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size, uint8_t is_indirect);
|
||||
rc_memref_t* rc_alloc_memref(rc_parse_state_t* parse, uint32_t address, uint8_t size);
|
||||
rc_modified_memref_t* rc_alloc_modified_memref(rc_parse_state_t* parse, uint8_t size, const rc_operand_t* parent,
|
||||
uint8_t modifier_type, const rc_operand_t* modifier);
|
||||
int rc_parse_memref(const char** memaddr, uint8_t* size, uint32_t* address);
|
||||
void rc_update_memref_values(rc_memref_t* memref, rc_peek_t peek, void* ud);
|
||||
void rc_update_memref_values(rc_memrefs_t* memrefs, rc_peek_t peek, void* ud);
|
||||
void rc_update_memref_value(rc_memref_value_t* memref, uint32_t value);
|
||||
uint32_t rc_get_memref_value(rc_memref_t* memref, int operand_type, rc_eval_state_t* eval_state);
|
||||
void rc_get_memref_value(rc_typed_value_t* value, rc_memref_t* memref, int operand_type);
|
||||
uint32_t rc_get_modified_memref_value(const rc_modified_memref_t* memref, rc_peek_t peek, void* ud);
|
||||
uint8_t rc_memref_shared_size(uint8_t size);
|
||||
uint32_t rc_memref_mask(uint8_t size);
|
||||
void rc_transform_memref_value(rc_typed_value_t* value, uint8_t size);
|
||||
uint32_t rc_peek_value(uint32_t address, uint8_t size, rc_peek_t peek, void* ud);
|
||||
|
||||
void rc_memrefs_init(rc_memrefs_t* memrefs);
|
||||
void rc_memrefs_destroy(rc_memrefs_t* memrefs);
|
||||
uint32_t rc_memrefs_count_memrefs(const rc_memrefs_t* memrefs);
|
||||
uint32_t rc_memrefs_count_modified_memrefs(const rc_memrefs_t* memrefs);
|
||||
|
||||
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||
int rc_trigger_state_active(int state);
|
||||
rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self);
|
||||
|
||||
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse, int is_value);
|
||||
typedef struct rc_condset_with_trailing_conditions_t {
|
||||
rc_condset_t condset;
|
||||
rc_condition_t conditions[2];
|
||||
} rc_condset_with_trailing_conditions_t;
|
||||
RC_ALLOW_ALIGN(rc_condset_with_trailing_conditions_t)
|
||||
|
||||
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse);
|
||||
int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state);
|
||||
void rc_reset_condset(rc_condset_t* self);
|
||||
rc_condition_t* rc_condset_get_conditions(rc_condset_t* self);
|
||||
|
||||
enum {
|
||||
RC_PROCESSING_COMPARE_DEFAULT = 0,
|
||||
@@ -161,24 +337,35 @@ enum {
|
||||
RC_PROCESSING_COMPARE_ALWAYS_FALSE
|
||||
};
|
||||
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect);
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse);
|
||||
void rc_parse_condition_internal(rc_condition_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||
void rc_condition_update_parse_state(rc_condition_t* condition, rc_parse_state_t* parse);
|
||||
int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state);
|
||||
void rc_evaluate_condition_value(rc_typed_value_t* value, rc_condition_t* self, rc_eval_state_t* eval_state);
|
||||
int rc_condition_is_combining(const rc_condition_t* self);
|
||||
void rc_condition_convert_to_operand(const rc_condition_t* condition, rc_operand_t* operand, rc_parse_state_t* parse);
|
||||
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indirect, rc_parse_state_t* parse);
|
||||
void rc_evaluate_operand(rc_typed_value_t* value, rc_operand_t* self, rc_eval_state_t* eval_state);
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||
void rc_evaluate_operand(rc_typed_value_t* value, const rc_operand_t* self, rc_eval_state_t* eval_state);
|
||||
int rc_operator_is_modifying(int oper);
|
||||
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_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);
|
||||
void rc_operand_set_float_const(rc_operand_t* self, double value);
|
||||
|
||||
int rc_is_valid_variable_character(char ch, int is_first);
|
||||
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||
int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t peek, void* ud, lua_State* L);
|
||||
void rc_reset_value(rc_value_t* self);
|
||||
int rc_value_from_hits(rc_value_t* self);
|
||||
rc_value_t* rc_alloc_helper_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse);
|
||||
void rc_update_variables(rc_value_t* variable, rc_peek_t peek, void* ud, lua_State* L);
|
||||
rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse);
|
||||
uint32_t rc_count_values(const rc_value_t* values);
|
||||
void rc_update_values(rc_value_t* values, rc_peek_t peek, void* ud, lua_State* L);
|
||||
void rc_reset_values(rc_value_t* values);
|
||||
|
||||
void rc_typed_value_convert(rc_typed_value_t* value, char new_type);
|
||||
void rc_typed_value_add(rc_typed_value_t* value, const rc_typed_value_t* amount);
|
||||
@@ -187,6 +374,7 @@ void rc_typed_value_divide(rc_typed_value_t* value, const rc_typed_value_t* amou
|
||||
void rc_typed_value_modulus(rc_typed_value_t* value, const rc_typed_value_t* amount);
|
||||
void rc_typed_value_negate(rc_typed_value_t* value);
|
||||
int rc_typed_value_compare(const rc_typed_value_t* value1, const rc_typed_value_t* value2, char oper);
|
||||
void rc_typed_value_combine(rc_typed_value_t* value, rc_typed_value_t* amount, uint8_t oper);
|
||||
void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref);
|
||||
|
||||
int rc_format_typed_value(char* buffer, size_t size, const rc_typed_value_t* value, int format);
|
||||
@@ -195,6 +383,11 @@ void rc_parse_lboard_internal(rc_lboard_t* self, const char* memaddr, rc_parse_s
|
||||
int rc_lboard_state_active(int state);
|
||||
|
||||
void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script, rc_parse_state_t* parse);
|
||||
rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self);
|
||||
void rc_reset_richpresence_triggers(rc_richpresence_t* self);
|
||||
|
||||
int rc_validate_memrefs(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t max_address);
|
||||
int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id);
|
||||
|
||||
RC_END_C_DECLS
|
||||
|
||||
|
||||
539
dep/rcheevos/src/rcheevos/rc_runtime_types.natvis
Normal file
539
dep/rcheevos/src/rcheevos/rc_runtime_types.natvis
Normal file
@@ -0,0 +1,539 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<!-- https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022 -->
|
||||
<!-- https://learn.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2022 -->
|
||||
<Type Name="rc_typed_value_t">
|
||||
<DisplayString Condition="type==RC_VALUE_TYPE_UNSIGNED">{value.u32} (RC_VALUE_TYPE_UNSIGNED)</DisplayString>
|
||||
<DisplayString Condition="type==RC_VALUE_TYPE_FLOAT">{value.f32} (RC_VALUE_TYPE_FLOAT)</DisplayString>
|
||||
<DisplayString Condition="type==RC_VALUE_TYPE_SIGNED">{value.i32} (RC_VALUE_TYPE_SIGNED)</DisplayString>
|
||||
<DisplayString Condition="type==RC_VALUE_TYPE_NONE">none (RC_VALUE_TYPE_NONE)</DisplayString>
|
||||
<DisplayString>{value.i32} (unknown)</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_bool_enum_t">
|
||||
<DisplayString Condition="value==0">false</DisplayString>
|
||||
<DisplayString Condition="value==1">true</DisplayString>
|
||||
<DisplayString>true ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_memsize_enum_t">
|
||||
<DisplayString Condition="value==RC_MEMSIZE_8_BITS">{RC_MEMSIZE_8_BITS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_16_BITS">{RC_MEMSIZE_16_BITS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_24_BITS">{RC_MEMSIZE_24_BITS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_32_BITS">{RC_MEMSIZE_32_BITS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_LOW">{RC_MEMSIZE_LOW}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_HIGH">{RC_MEMSIZE_HIGH}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_0">{RC_MEMSIZE_BIT_0}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_1">{RC_MEMSIZE_BIT_1}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_2">{RC_MEMSIZE_BIT_2}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_3">{RC_MEMSIZE_BIT_3}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_4">{RC_MEMSIZE_BIT_4}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_5">{RC_MEMSIZE_BIT_5}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_6">{RC_MEMSIZE_BIT_6}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_7">{RC_MEMSIZE_BIT_7}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BITCOUNT">{RC_MEMSIZE_BITCOUNT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_16_BITS_BE">{RC_MEMSIZE_16_BITS_BE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_24_BITS_BE">{RC_MEMSIZE_24_BITS_BE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_32_BITS_BE">{RC_MEMSIZE_32_BITS_BE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_FLOAT">{RC_MEMSIZE_FLOAT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_MBF32">{RC_MEMSIZE_MBF32}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_MBF32_LE">{RC_MEMSIZE_MBF32_LE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_FLOAT_BE">{RC_MEMSIZE_FLOAT_BE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_DOUBLE32">{RC_MEMSIZE_DOUBLE32}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_DOUBLE32_BE">{RC_MEMSIZE_DOUBLE32_BE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_VARIABLE">{RC_MEMSIZE_VARIABLE}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_value_type_enum_t">
|
||||
<DisplayString Condition="value==RC_VALUE_TYPE_NONE">{RC_VALUE_TYPE_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_VALUE_TYPE_UNSIGNED">{RC_VALUE_TYPE_UNSIGNED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_VALUE_TYPE_SIGNED">{RC_VALUE_TYPE_SIGNED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_VALUE_TYPE_FLOAT">{RC_VALUE_TYPE_FLOAT}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_memref_type_enum_t">
|
||||
<DisplayString Condition="value==RC_MEMREF_TYPE_MEMREF">{RC_MEMREF_TYPE_MEMREF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMREF_TYPE_MODIFIED_MEMREF">{RC_MEMREF_TYPE_MODIFIED_MEMREF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMREF_TYPE_VALUE">RC_MEMREF_TYPE_VALUE</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_memsize_enum_func_t">
|
||||
<DisplayString Condition="value==RC_MEMSIZE_8_BITS">byte</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_16_BITS">word</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_24_BITS">tbyte</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_32_BITS">dword</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_LOW">lower4</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_HIGH">upper4</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_0">bit0</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_1">bit1</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_2">bit2</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_3">bit3</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_4">bit4</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_5">bit5</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_6">bit6</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BIT_7">bit7</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_BITCOUNT">bitcount</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_16_BITS_BE">word_be</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_24_BITS_BE">tbyte_be</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_32_BITS_BE">dword_be</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_FLOAT">float</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_MBF32">mbf32</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_MBF32_LE">mbf32_le</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_FLOAT_BE">float_be</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_DOUBLE32">double32</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_DOUBLE32_BE">double32_be</DisplayString>
|
||||
<DisplayString Condition="value==RC_MEMSIZE_VARIABLE">var</DisplayString>
|
||||
<DisplayString>unknown</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_memref_value_t">
|
||||
<DisplayString Condition="type==RC_VALUE_TYPE_FLOAT">{{value={(float)*((float*)&value)} prior={(float)*((float*)&prior)}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_VALUE_TYPE_SIGNED">{{value={(int)value} prior={(int)prior}}}</DisplayString>
|
||||
<DisplayString>{{value={value,x} prior={prior,x}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="value">value</Item>
|
||||
<Item Name="prior">prior</Item>
|
||||
<Item Name="size">*((__rc_memsize_enum_t*)&size)</Item>
|
||||
<Item Name="changed">*((__rc_bool_enum_t*)&changed)</Item>
|
||||
<Item Name="type">*((__rc_value_type_enum_t*)&type)</Item>
|
||||
<Item Name="memref_type">*((__rc_memref_type_enum_t*)&memref_type)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_memref_t">
|
||||
<DisplayString Condition="value.memref_type==RC_MEMREF_TYPE_MODIFIED_MEMREF">{*(rc_modified_memref_t*)&value}</DisplayString>
|
||||
<DisplayString Condition="value.memref_type==RC_MEMREF_TYPE_VALUE">{*(rc_value_t*)&value}</DisplayString>
|
||||
<DisplayString Condition="value.size==RC_MEMSIZE_VARIABLE">var</DisplayString>
|
||||
<DisplayString>{*((__rc_memsize_enum_func_t*)&value.size)}({address,x})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[rc_modified_memref_t]" Condition="value.memref_type==RC_MEMREF_TYPE_MODIFIED_MEMREF">(rc_modified_memref_t*)&value</Item>
|
||||
<Item Name="value">value</Item>
|
||||
<Item Name="address">address</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_memref_list_t">
|
||||
<DisplayString>{{count = {count}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="next" Condition="next!=0">next</Item>
|
||||
<Item Name="count">count</Item>
|
||||
<Item Name="capacity">capacity</Item>
|
||||
<ArrayItems>
|
||||
<Size>count</Size>
|
||||
<ValuePointer>items</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_operand_memref_t">
|
||||
<DisplayString Condition="operand.value.memref->value.memref_type==RC_MEMREF_TYPE_MODIFIED_MEMREF">... {*((__rc_memsize_enum_func_t*)&operand.size)} {operand.value.memref->address,x}</DisplayString>
|
||||
<DisplayString Condition="operand.value.memref->value.memref_type==RC_MEMREF_TYPE_VALUE">value {((rc_value_t*)operand.value.memref)->name,s}</DisplayString>
|
||||
<DisplayString>{*((__rc_memsize_enum_func_t*)&operand.size)} {operand.value.memref->address,x}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[rc_modified_memref_t]" Condition="operand.value.memref->value.memref_type==RC_MEMREF_TYPE_MODIFIED_MEMREF">(rc_modified_memref_t*)&operand.value</Item>
|
||||
<Item Name="value">operand.value.memref->value</Item>
|
||||
<Item Name="address">operand.value.memref->address</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_operand_enum_t">
|
||||
<DisplayString Condition="value==RC_OPERAND_ADDRESS">{RC_OPERAND_ADDRESS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_DELTA">{RC_OPERAND_DELTA}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_CONST">{RC_OPERAND_CONST}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_FP">{RC_OPERAND_FP}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_LUA">{RC_OPERAND_LUA}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_PRIOR">{RC_OPERAND_PRIOR}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_BCD">{RC_OPERAND_BCD}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_INVERTED">{RC_OPERAND_INVERTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERAND_RECALL">{RC_OPERAND_RECALL}</DisplayString>
|
||||
<DisplayString Condition="value==0xFF">RC_OPERAND_NONE (255)</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_operand_t">
|
||||
<DisplayString Condition="type==RC_OPERAND_ADDRESS">{{{*(__rc_operand_memref_t*)&value.memref}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_DELTA">{{delta {*(__rc_operand_memref_t*)&value.memref}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_PRIOR">{{prior {*(__rc_operand_memref_t*)&value.memref}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_BCD">{{bcd {*(__rc_operand_memref_t*)&value.memref}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_INVERTED">{{inverted {*(__rc_operand_memref_t*)&value.memref}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_CONST && value.num > 0xFFFF0000">{{value {(int)value.num}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_CONST && value.num > 0x01000000">{{value {value.num,x}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_CONST">{{value {value.num}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_FP">{{value {value.dbl}}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_RECALL">{{recall}}</DisplayString>
|
||||
<DisplayString Condition="type==RC_OPERAND_LUA">{{lua @{value.luafunc}}}</DisplayString>
|
||||
<DisplayString Condition="type==0xFF">{{none}}</DisplayString>
|
||||
<DisplayString>{{unknown}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="value" Condition="type==RC_OPERAND_CONST">value.num</Item>
|
||||
<Item Name="value" Condition="type==RC_OPERAND_FP">value.dbl</Item>
|
||||
<Item Name="value" Condition="type==RC_OPERAND_RECALL && memref_access_type==RC_OPERAND_CONST">value.num</Item>
|
||||
<Item Name="value" Condition="type==RC_OPERAND_RECALL && memref_access_type==RC_OPERAND_FP">value.dbl</Item>
|
||||
<Item Name="value" Condition="type!=RC_OPERAND_CONST && type!=RC_OPERAND_FP && value.memref==0">value.memref</Item>
|
||||
<Item Name="value" Condition="type!=RC_OPERAND_CONST && type!=RC_OPERAND_FP && ((rc_memref_t*)value.memref)->value.memref_type!=RC_MEMREF_TYPE_MODIFIED_MEMREF">value.memref</Item>
|
||||
<Item Name="value" Condition="type!=RC_OPERAND_CONST && type!=RC_OPERAND_FP && ((rc_memref_t*)value.memref)->value.memref_type==RC_MEMREF_TYPE_MODIFIED_MEMREF">(rc_modified_memref_t*)value.memref</Item>
|
||||
<Item Name="type">*((__rc_operand_enum_t*)&type)</Item>
|
||||
<Item Name="size">*((__rc_memsize_enum_t*)&size)</Item>
|
||||
<Item Name="memref_access_type">*((__rc_operand_enum_t*)&memref_access_type)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_condition_enum_t">
|
||||
<DisplayString Condition="value==RC_CONDITION_STANDARD">{RC_CONDITION_STANDARD}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_PAUSE_IF">{RC_CONDITION_PAUSE_IF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_RESET_IF">{RC_CONDITION_RESET_IF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_MEASURED_IF">{RC_CONDITION_MEASURED_IF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_TRIGGER">{RC_CONDITION_TRIGGER}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_MEASURED">{RC_CONDITION_MEASURED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_ADD_SOURCE">{RC_CONDITION_ADD_SOURCE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_SUB_SOURCE">{RC_CONDITION_SUB_SOURCE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_ADD_ADDRESS">{RC_CONDITION_ADD_ADDRESS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_REMEMBER">{RC_CONDITION_REMEMBER}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_ADD_HITS">{RC_CONDITION_ADD_HITS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_SUB_HITS">{RC_CONDITION_SUB_HITS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_RESET_NEXT_IF">{RC_CONDITION_RESET_NEXT_IF}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_AND_NEXT">{RC_CONDITION_AND_NEXT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_OR_NEXT">{RC_CONDITION_OR_NEXT}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_condition_enum_str_t">
|
||||
<DisplayString Condition="value==RC_CONDITION_STANDARD"></DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_PAUSE_IF">PauseIf </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_RESET_IF">ResetIf </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_MEASURED_IF">MeasuredIf </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_TRIGGER">Trigger </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_MEASURED">Measured </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_ADD_SOURCE">AddSource </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_SUB_SOURCE">SubSource </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_ADD_ADDRESS">AddAddress </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_REMEMBER">Remember </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_ADD_HITS">AddHits </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_SUB_HITS">SubHits </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_RESET_NEXT_IF">ResetNextIf </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_AND_NEXT">AndNext </DisplayString>
|
||||
<DisplayString Condition="value==RC_CONDITION_OR_NEXT">OrNext </DisplayString>
|
||||
<DisplayString>{value} </DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_operator_enum_t">
|
||||
<DisplayString Condition="value==RC_OPERATOR_EQ">{RC_OPERATOR_EQ}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_LT">{RC_OPERATOR_LT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_LE">{RC_OPERATOR_LE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_GT">{RC_OPERATOR_GT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_GE">{RC_OPERATOR_GE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_NE">{RC_OPERATOR_NE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_NONE">{RC_OPERATOR_NONE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_MULT">{RC_OPERATOR_MULT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_DIV">{RC_OPERATOR_DIV}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_AND">{RC_OPERATOR_AND}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_XOR">{RC_OPERATOR_XOR}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_MOD">{RC_OPERATOR_MOD}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_ADD">{RC_OPERATOR_ADD}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_SUB">{RC_OPERATOR_SUB}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_SUB_PARENT">{RC_OPERATOR_SUB_PARENT}</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_INDIRECT_READ">{RC_OPERATOR_INDIRECT_READ}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="__rc_operator_enum_str_t">
|
||||
<DisplayString Condition="value==RC_OPERATOR_EQ">==</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_LT"><</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_LE"><=</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_GT">></DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_GE">>=</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_NE">!=</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_NONE"> </DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_MULT">*</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_DIV">/</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_AND">&</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_XOR">^</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_MOD">%</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_ADD">+</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_SUB">-</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_SUB_PARENT">subtracted from</DisplayString>
|
||||
<DisplayString Condition="value==RC_OPERATOR_INDIRECT_READ">$</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_condition_t">
|
||||
<DisplayString Condition="oper==RC_OPERATOR_NONE && required_hits==0">{*((__rc_condition_enum_str_t*)&type)} {operand1}</DisplayString>
|
||||
<DisplayString Condition="oper==RC_OPERATOR_NONE">{*((__rc_condition_enum_str_t*)&type)} {operand1} ({required_hits})</DisplayString>
|
||||
<DisplayString Condition="required_hits==0">{*((__rc_condition_enum_str_t*)&type)} {operand1} {*((__rc_operator_enum_str_t*)&oper)} {operand2}</DisplayString>
|
||||
<DisplayString>{*((__rc_condition_enum_str_t*)&type)} {operand1} {*((__rc_operator_enum_str_t*)&oper)} {operand2} ({required_hits})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="type">*((__rc_condition_enum_t*)&type)</Item>
|
||||
<Item Name="operand1">operand1</Item>
|
||||
<Item Name="oper">*((__rc_operator_enum_t*)&oper)</Item>
|
||||
<Item Name="operand2">operand2</Item>
|
||||
<Item Name="required_hits">required_hits</Item>
|
||||
<Item Name="current_hits">current_hits</Item>
|
||||
<Item Name="next">next</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_condset_t">
|
||||
<DisplayString>{{count={num_pause_conditions+num_reset_conditions+num_hittarget_conditions+num_measured_conditions+num_other_conditions+num_indirect_conditions}}}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>conditions</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_condset_list_t">
|
||||
<DisplayString Condition="first_condset==0">{{}}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first_condset</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_modified_memref_t">
|
||||
<DisplayString Condition="modifier_type==RC_OPERATOR_INDIRECT_READ">$({parent} + {modifier})</DisplayString>
|
||||
<DisplayString Condition="modifier_type==RC_OPERATOR_SUB_PARENT">({modifier} - {parent})</DisplayString>
|
||||
<DisplayString>({parent} {*((__rc_operator_enum_str_t*)&modifier_type)} {modifier})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="value">memref.value</Item>
|
||||
<Item Name="parent">parent</Item>
|
||||
<Item Name="modifier_type">*((__rc_operator_enum_t*)&modifier_type)</Item>
|
||||
<Item Name="modifier">modifier</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_modified_memref_list_t">
|
||||
<DisplayString>{{count = {count}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="next" Condition="next!=0">next</Item>
|
||||
<Item Name="count">count</Item>
|
||||
<Item Name="capacity">capacity</Item>
|
||||
<ArrayItems>
|
||||
<Size>count</Size>
|
||||
<ValuePointer>items</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_trigger_state_enum_t">
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_INACTIVE">{RC_TRIGGER_STATE_INACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_WAITING">{RC_TRIGGER_STATE_WAITING}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_ACTIVE">{RC_TRIGGER_STATE_ACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_PAUSED">{RC_TRIGGER_STATE_PAUSED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_RESET">{RC_TRIGGER_STATE_RESET}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_TRIGGERED">{RC_TRIGGER_STATE_TRIGGERED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_PRIMED">{RC_TRIGGER_STATE_PRIMED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_TRIGGER_STATE_DISABLED">{RC_TRIGGER_STATE_DISABLED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_trigger_t">
|
||||
<Expand>
|
||||
<Item Name="state">*((__rc_trigger_state_enum_t*)&state)</Item>
|
||||
<Item Name="has_hits">*((__rc_bool_enum_t*)&has_hits)</Item>
|
||||
<Item Name="measured_as_percent">*((__rc_bool_enum_t*)&measured_as_percent)</Item>
|
||||
<Item Name="requirement">requirement</Item>
|
||||
<Item Name="alternative">*((__rc_condset_list_t*)&alternative)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_value_t">
|
||||
<DisplayString>{value} {name,s}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="value">value</Item>
|
||||
<Item Name="conditions">conditions</Item>
|
||||
<Item Name="name">name</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_value_list_t">
|
||||
<DisplayString>{{count = {count}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="count">count</Item>
|
||||
<Item Name="capacity">capacity</Item>
|
||||
<ArrayItems>
|
||||
<Size>count</Size>
|
||||
<ValuePointer>items</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_lboard_state_enum_t">
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_INACTIVE">{RC_LBOARD_STATE_INACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_WAITING">{RC_LBOARD_STATE_WAITING}</DisplayString>
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_ACTIVE">{RC_LBOARD_STATE_ACTIVE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_STARTED">{RC_LBOARD_STATE_STARTED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_CANCELED">{RC_LBOARD_STATE_CANCELED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_TRIGGERED">{RC_LBOARD_STATE_TRIGGERED}</DisplayString>
|
||||
<DisplayString Condition="value==RC_LBOARD_STATE_DISABLED">{RC_LBOARD_STATE_DISABLED}</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_lboard_t">
|
||||
<Expand>
|
||||
<Item Name="state">*((__rc_lboard_state_enum_t*)&state)</Item>
|
||||
<Item Name="start">start</Item>
|
||||
<Item Name="submit">submit</Item>
|
||||
<Item Name="cancel">cancel</Item>
|
||||
<Item Name="value">value</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_format_enum_t">
|
||||
<DisplayString Condition="value==RC_FORMAT_FRAMES">{RC_FORMAT_FRAMES}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_SECONDS">{RC_FORMAT_SECONDS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_CENTISECS">{RC_FORMAT_CENTISECS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_SCORE">{RC_FORMAT_SCORE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_VALUE">{RC_FORMAT_VALUE}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_MINUTES">{RC_FORMAT_MINUTES}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_SECONDS_AS_MINUTES">{RC_FORMAT_SECONDS_AS_MINUTES}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FLOAT1">{RC_FORMAT_FLOAT1}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FLOAT2">{RC_FORMAT_FLOAT2}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FLOAT3">{RC_FORMAT_FLOAT3}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FLOAT4">{RC_FORMAT_FLOAT4}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FLOAT5">{RC_FORMAT_FLOAT5}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FLOAT6">{RC_FORMAT_FLOAT6}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FIXED1">{RC_FORMAT_FIXED1}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FIXED2">{RC_FORMAT_FIXED2}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_FIXED3">{RC_FORMAT_FIXED3}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_TENS">{RC_FORMAT_TENS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_HUNDREDS">{RC_FORMAT_HUNDREDS}</DisplayString>
|
||||
<DisplayString Condition="value==RC_FORMAT_THOUSANDS">{RC_FORMAT_THOUSANDS}</DisplayString>
|
||||
<DisplayString Condition="value==101">RC_FORMAT_STRING (101)</DisplayString>
|
||||
<DisplayString Condition="value==102">RC_FORMAT_LOOKUP (102)</DisplayString>
|
||||
<DisplayString Condition="value==103">RC_FORMAT_UNKNOWN_MACRO (103)</DisplayString>
|
||||
<DisplayString Condition="value==104">RC_FORMAT_ASCIICHAR (104)</DisplayString>
|
||||
<DisplayString Condition="value==105">RC_FORMAT_UNICODECHAR (105)</DisplayString>
|
||||
<DisplayString>unknown ({value})</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_richpresence_display_part_t">
|
||||
<DisplayString Condition="display_type==101">{text,s}</DisplayString>
|
||||
<DisplayString Condition="display_type==103">[Unknown macro]{text,sb}</DisplayString>
|
||||
<DisplayString Condition="lookup==0">@{text,sb}({value,na})</DisplayString>
|
||||
<DisplayString>@{lookup->name,sb}({value,na})</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="text" Condition="display_type==101||display_type==103">text</Item>
|
||||
<Item Name="lookup" Condition="display_type!=101&&display_type!=103">lookup</Item>
|
||||
<Item Name="value" Condition="display_type!=101&&display_type!=103">value</Item>
|
||||
<Item Name="display_type">*((__rc_format_enum_t*)&display_type)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_richpresence_display_part_list_t">
|
||||
<DisplayString Condition="display->next->next!=0">{display,na} {display->next,na} {display->next->next,na}</DisplayString>
|
||||
<DisplayString Condition="display->next!=0">{display,na} {display->next,na}</DisplayString>
|
||||
<DisplayString>{display,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>display</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_richpresence_display_t">
|
||||
<Expand>
|
||||
<Item Name="displays">*((__rc_richpresence_display_part_list_t*)&display)</Item>
|
||||
<Item Name="trigger">trigger</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_richpresence_display_list_t">
|
||||
<DisplayString Condition="first_display==0">{{NULL}}</DisplayString>
|
||||
<DisplayString>{(void*)&first_display,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first_display</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_richpresence_lookup_item_t">
|
||||
<DisplayString Condition="first==last">{first}: {label,na}</DisplayString>
|
||||
<DisplayString>{first}-{last}: {label,na}</DisplayString>
|
||||
</Type>
|
||||
<Type Name="rc_richpresence_lookup_t">
|
||||
<DisplayString>{name,na}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="name">name</Item>
|
||||
<Item Name="format">*((__rc_format_enum_t*)&format)</Item>
|
||||
<Item Name="default_label" Condition="format>101">default_label</Item>
|
||||
<TreeItems>
|
||||
<HeadPointer>root</HeadPointer>
|
||||
<LeftPointer>left</LeftPointer>
|
||||
<RightPointer>right</RightPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</TreeItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_richpresence_lookup_list_t">
|
||||
<DisplayString Condition="first_lookup==0">{{NULL}}</DisplayString>
|
||||
<DisplayString>{(void*)&first_lookup,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first_lookup</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_richpresence_t">
|
||||
<Expand>
|
||||
<Item Name="displays">((__rc_richpresence_display_list_t*)&first_display)</Item>
|
||||
<Item Name="lookups">((__rc_richpresence_lookup_list_t*)&first_lookup)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_value_list_t">
|
||||
<DisplayString Condition="first_value==0">{{NULL}}</DisplayString>
|
||||
<DisplayString>{(void*)&first_value,na}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>first_value</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_parse_state_t">
|
||||
<DisplayString>{{offset={offset} addsource_parent={addsource_parent} indirect_parent={indirect_parent}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="offset">offset</Item>
|
||||
<Item Name="memrefs">memrefs</Item>
|
||||
<Item Name="existing_memrefs">existing_memrefs</Item>
|
||||
<Item Name="variables" Condition="variables==0">variables</Item>
|
||||
<Item Name="variables" Condition="variables!=0">((__rc_value_list_t*)&variables)</Item>
|
||||
<Item Name="addsource_parent">addsource_parent</Item>
|
||||
<Item Name="addsource_oper">*((__rc_operator_enum_t*)&addsource_oper)</Item>
|
||||
<Item Name="indirect_parent">indirect_parent</Item>
|
||||
<Item Name="remember">remember</Item>
|
||||
<Item Name="is_value">*((__rc_bool_enum_t*)&is_value)</Item>
|
||||
<Item Name="has_required_hits">*((__rc_bool_enum_t*)&has_required_hits)</Item>
|
||||
<Item Name="measured_as_percent">*((__rc_bool_enum_t*)&measured_as_percent)</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_buffer_chunk_t">
|
||||
<DisplayString>{{used={write-start} size={end-start}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[size]">end-start</Item>
|
||||
<Item Name="[used]">write-start</Item>
|
||||
<Item Name="[available]">end-write</Item>
|
||||
<Item Name="next">next</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_buffer_t">
|
||||
<DisplayString></DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<HeadPointer>&chunk</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_runtime_trigger_list_t">
|
||||
<DisplayString>{{count={runtime.trigger_count}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>runtime.trigger_count</Size>
|
||||
<ValueNode>runtime.triggers[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="__rc_runtime_lboard_list_t">
|
||||
<DisplayString>{{count={runtime.lboard_count}}}</DisplayString>
|
||||
<Expand>
|
||||
<IndexListItems>
|
||||
<Size>runtime.lboard_count</Size>
|
||||
<ValueNode>runtime.lboards[$i]</ValueNode>
|
||||
</IndexListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="rc_runtime_t">
|
||||
<DisplayString>{{trigger_count={trigger_count} lboard_count={lboard_count}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="triggers">*((__rc_runtime_trigger_list_t*)this)</Item>
|
||||
<Item Name="lboards">*((__rc_runtime_lboard_list_t*)this)</Item>
|
||||
<Item Name="richpresence">richpresence</Item>
|
||||
<Item Name="memrefs">memrefs</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
||||
@@ -17,6 +17,7 @@ static int rc_validate_memref(const rc_memref_t* memref, char result[], const si
|
||||
|
||||
switch (console_id) {
|
||||
case RC_CONSOLE_NINTENDO:
|
||||
case RC_CONSOLE_FAMICOM_DISK_SYSTEM:
|
||||
if (memref->address >= 0x0800 && memref->address <= 0x1FFF) {
|
||||
snprintf(result, result_size, "Mirror RAM may not be exposed by emulator (address %04X)", memref->address);
|
||||
return 0;
|
||||
@@ -42,14 +43,19 @@ static int rc_validate_memref(const rc_memref_t* memref, char result[], const si
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address)
|
||||
int rc_validate_memrefs(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t max_address)
|
||||
{
|
||||
while (memref) {
|
||||
if (!rc_validate_memref(memref, result, result_size, 0, max_address))
|
||||
return 0;
|
||||
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
do {
|
||||
const rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_stop = memref + memref_list->count;
|
||||
for (; memref < memref_stop; ++memref) {
|
||||
if (!rc_validate_memref(memref, result, result_size, 0, max_address))
|
||||
return 0;
|
||||
}
|
||||
|
||||
memref = memref->next;
|
||||
}
|
||||
memref_list = memref_list->next;
|
||||
} while (memref_list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -64,15 +70,22 @@ static uint32_t rc_console_max_address(uint32_t console_id)
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id)
|
||||
int rc_validate_memrefs_for_console(const rc_memrefs_t* memrefs, char result[], const size_t result_size, uint32_t console_id)
|
||||
{
|
||||
const uint32_t max_address = rc_console_max_address(console_id);
|
||||
while (memref) {
|
||||
if (!rc_validate_memref(memref, result, result_size, console_id, max_address))
|
||||
return 0;
|
||||
const rc_memref_list_t* memref_list = &memrefs->memrefs;
|
||||
do
|
||||
{
|
||||
const rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_stop = memref + memref_list->count;
|
||||
for (; memref < memref_stop; ++memref)
|
||||
{
|
||||
if (!rc_validate_memref(memref, result, result_size, console_id, max_address))
|
||||
return 0;
|
||||
}
|
||||
|
||||
memref = memref->next;
|
||||
}
|
||||
memref_list = memref_list->next;
|
||||
} while (memref_list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -104,6 +117,7 @@ static uint32_t rc_max_value(const rc_operand_t* operand)
|
||||
return 8;
|
||||
|
||||
case RC_MEMSIZE_8_BITS:
|
||||
/* NOTE: BCD should max out at 0x99, but because each digit can be 15, it actually maxes at 15*10 + 15 */
|
||||
return (operand->type == RC_OPERAND_BCD) ? 165 : 0xFF;
|
||||
|
||||
case RC_MEMSIZE_16_BITS:
|
||||
@@ -160,10 +174,18 @@ static uint32_t rc_scale_value(uint32_t value, uint8_t oper, const rc_operand_t*
|
||||
|
||||
case RC_OPERATOR_SUB:
|
||||
{
|
||||
if (operand->type == RC_OPERAND_CONST)
|
||||
return value - operand->value.num;
|
||||
else if (value > rc_max_value(operand))
|
||||
return value - rc_max_value(operand);
|
||||
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : rc_max_value(operand);
|
||||
if (value > op_max)
|
||||
return value - op_max;
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
case RC_OPERATOR_SUB_PARENT:
|
||||
{
|
||||
const uint32_t op_max = (operand->type == RC_OPERAND_CONST) ? operand->value.num : rc_max_value(operand);
|
||||
if (op_max > value)
|
||||
return op_max - value;
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
@@ -173,6 +195,17 @@ static uint32_t rc_scale_value(uint32_t value, uint8_t oper, const rc_operand_t*
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rc_max_chain_value(const rc_operand_t* operand)
|
||||
{
|
||||
if (rc_operand_is_memref(operand) && operand->value.memref->value.memref_type == RC_MEMREF_TYPE_MODIFIED_MEMREF) {
|
||||
const rc_modified_memref_t* modified_memref = (const rc_modified_memref_t*)operand->value.memref;
|
||||
const uint32_t op_max = rc_max_chain_value(&modified_memref->parent);
|
||||
return rc_scale_value(op_max, modified_memref->modifier_type, &modified_memref->modifier);
|
||||
}
|
||||
|
||||
return rc_max_value(operand);
|
||||
}
|
||||
|
||||
static int rc_validate_get_condition_index(const rc_condset_t* condset, const rc_condition_t* condition)
|
||||
{
|
||||
int index = 1;
|
||||
@@ -256,18 +289,14 @@ static int rc_validate_range(uint32_t min_val, uint32_t max_val, char oper, uint
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc_validate_condset_internal(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address)
|
||||
static int rc_validate_condset_internal(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id, uint32_t max_address)
|
||||
{
|
||||
const rc_condition_t* cond;
|
||||
char buffer[128];
|
||||
uint32_t max_val;
|
||||
int index = 1;
|
||||
unsigned long long add_source_max = 0;
|
||||
int in_add_hits = 0;
|
||||
int in_add_address = 0;
|
||||
int is_combining = 0;
|
||||
int remember_used = 0;
|
||||
int remember_used_in_pause = 0;
|
||||
|
||||
if (!condset) {
|
||||
*result = '\0';
|
||||
@@ -275,10 +304,8 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
}
|
||||
|
||||
for (cond = condset->conditions; cond; cond = cond->next, ++index) {
|
||||
uint32_t max = rc_max_value(&cond->operand1);
|
||||
const int is_memref1 = rc_operand_is_memref(&cond->operand1);
|
||||
const int is_memref2 = rc_operand_is_memref(&cond->operand2);
|
||||
const int uses_recall = rc_operand_is_recall(&cond->operand1) || rc_operand_is_recall(&cond->operand2);
|
||||
|
||||
if (!in_add_address) {
|
||||
if (is_memref1 && !rc_validate_memref(cond->operand1.value.memref, buffer, sizeof(buffer), console_id, max_address)) {
|
||||
@@ -294,39 +321,24 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
in_add_address = 0;
|
||||
}
|
||||
|
||||
if (!remember_used && uses_recall) {
|
||||
if (!cond->pause && condset->has_pause) {
|
||||
/* pause conditions will be processed before non-pause conditions.
|
||||
* scan forward for any remembers in yet-to-be-processed pause conditions */
|
||||
const rc_condition_t* cond_rem_pause_check = cond->next;
|
||||
for (; cond_rem_pause_check; cond_rem_pause_check = cond_rem_pause_check->next) {
|
||||
if (cond_rem_pause_check->type == RC_CONDITION_REMEMBER && cond_rem_pause_check->pause) {
|
||||
remember_used = 1; /* do not set remember_used_in_pause here because we don't know at which poing in the pause processing this remember is occurring. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!remember_used) {
|
||||
if (rc_operand_is_recall(&cond->operand1)) {
|
||||
if (rc_operand_type_is_memref(cond->operand1.memref_access_type) && !cond->operand1.value.memref) {
|
||||
snprintf(result, result_size, "Condition %d: Recall used before Remember", index);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (cond->pause && uses_recall && !remember_used_in_pause) {
|
||||
snprintf(result, result_size, "Condition %d: Recall used in Pause processing before Remember was used in Pause processing", index);
|
||||
return 0;
|
||||
|
||||
if (rc_operand_is_recall(&cond->operand2)) {
|
||||
if (rc_operand_type_is_memref(cond->operand2.memref_access_type) && !cond->operand2.value.memref) {
|
||||
snprintf(result, result_size, "Condition %d: Recall used before Remember", index);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cond->type) {
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
max = rc_scale_value(max, cond->oper, &cond->operand2);
|
||||
add_source_max += max;
|
||||
is_combining = 1;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
max = rc_scale_value(max, cond->oper, &cond->operand2);
|
||||
if (add_source_max < max) /* potential underflow - may be expected */
|
||||
add_source_max = 0xFFFFFFFF;
|
||||
case RC_CONDITION_REMEMBER:
|
||||
is_combining = 1;
|
||||
continue;
|
||||
|
||||
@@ -339,12 +351,6 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
is_combining = 1;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_REMEMBER:
|
||||
is_combining = 1;
|
||||
remember_used = 1;
|
||||
remember_used_in_pause += cond->pause;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_SUB_HITS:
|
||||
in_add_hits = 1;
|
||||
@@ -377,18 +383,11 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
break;
|
||||
}
|
||||
|
||||
/* if we're in an add source chain, check for overflow */
|
||||
if (add_source_max) {
|
||||
const unsigned long long overflow = add_source_max + max;
|
||||
if (overflow > 0xFFFFFFFFUL)
|
||||
max = 0xFFFFFFFF;
|
||||
else
|
||||
max += (unsigned)add_source_max;
|
||||
}
|
||||
|
||||
/* check for comparing two differently sized memrefs */
|
||||
max_val = rc_max_value(&cond->operand2);
|
||||
if (max_val != max && add_source_max == 0 && is_memref1 && is_memref2) {
|
||||
if (is_memref1 && is_memref2 &&
|
||||
cond->operand1.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF &&
|
||||
cond->operand2.value.memref->value.memref_type == RC_MEMREF_TYPE_MEMREF &&
|
||||
rc_max_value(&cond->operand1) != rc_max_value(&cond->operand2)) {
|
||||
snprintf(result, result_size, "Condition %d: Comparing different memory sizes", index);
|
||||
return 0;
|
||||
}
|
||||
@@ -396,19 +395,23 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
if (is_memref1 && rc_operand_is_float(&cond->operand1)) {
|
||||
/* if left side is a float, right side will be converted to a float, so don't do range validation */
|
||||
}
|
||||
else if (is_memref1 || is_memref2 || add_source_max) {
|
||||
/* if either side is a memref, or there's a running add source chain, check for impossible comparisons */
|
||||
else if (is_memref1 || is_memref2) {
|
||||
/* if either side is a memref, check for impossible comparisons */
|
||||
const size_t prefix_length = snprintf(result, result_size, "Condition %d: ", index);
|
||||
const rc_operand_t* operand1 = &cond->operand1;
|
||||
const rc_operand_t* operand2 = &cond->operand2;
|
||||
uint8_t oper = cond->oper;
|
||||
uint32_t max = rc_max_chain_value(operand1);
|
||||
uint32_t max_val = rc_max_value(operand2);
|
||||
uint32_t min_val;
|
||||
|
||||
if (!is_memref1 && !add_source_max) {
|
||||
if (!is_memref1) {
|
||||
/* pretend constant was on right side */
|
||||
operand1 = &cond->operand2;
|
||||
operand2 = &cond->operand1;
|
||||
max = max_val;
|
||||
max_val = max;
|
||||
max = rc_max_value(&cond->operand2);
|
||||
|
||||
switch (oper) {
|
||||
case RC_OPERATOR_LT: oper = RC_OPERATOR_GT; break;
|
||||
case RC_OPERATOR_LE: oper = RC_OPERATOR_GE; break;
|
||||
@@ -426,8 +429,7 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
min_val = (int)operand2->value.dbl;
|
||||
|
||||
/* cannot compare an integer memory reference to a non-integral floating point value */
|
||||
if (!add_source_max && !rc_operand_is_float_memref(operand1) &&
|
||||
(float)min_val != operand2->value.dbl) {
|
||||
if (!rc_operand_is_float_memref(operand1) && (float)min_val != operand2->value.dbl) {
|
||||
switch (oper) {
|
||||
case RC_OPERATOR_EQ:
|
||||
snprintf(result + prefix_length, result_size - prefix_length, "Comparison is never true");
|
||||
@@ -455,8 +457,6 @@ int rc_validate_condset_internal(const rc_condset_t* condset, char result[], con
|
||||
if (!rc_validate_range(min_val, max_val, oper, max, result + prefix_length, result_size - prefix_length))
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_source_max = 0;
|
||||
}
|
||||
|
||||
if (is_combining) {
|
||||
@@ -697,24 +697,6 @@ static int rc_validate_comparison_overlap(int comparison1, uint32_t value1, int
|
||||
return RC_OVERLAP_NONE;
|
||||
}
|
||||
|
||||
static int rc_validate_are_operands_equal(const rc_operand_t* oper1, const rc_operand_t* oper2)
|
||||
{
|
||||
if (oper1->type != oper2->type)
|
||||
return 0;
|
||||
|
||||
switch (oper1->type)
|
||||
{
|
||||
case RC_OPERAND_CONST:
|
||||
return (oper1->value.num == oper2->value.num);
|
||||
case RC_OPERAND_FP:
|
||||
return (oper1->value.dbl == oper2->value.dbl);
|
||||
case RC_OPERAND_RECALL:
|
||||
return (oper2->type == RC_OPERAND_RECALL);
|
||||
default:
|
||||
return (oper1->value.memref->address == oper2->value.memref->address && oper1->size == oper2->size);
|
||||
}
|
||||
}
|
||||
|
||||
static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, const rc_condset_t* compare_conditions,
|
||||
const char* prefix, const char* compare_prefix, char result[], const size_t result_size)
|
||||
{
|
||||
@@ -736,7 +718,7 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
|
||||
for (condition = conditions->conditions; condition != NULL; condition = condition->next)
|
||||
{
|
||||
condition_chain_start = condition;
|
||||
while (rc_condition_is_combining(condition))
|
||||
while (condition && rc_condition_is_combining(condition))
|
||||
condition = condition->next;
|
||||
if (!condition)
|
||||
break;
|
||||
@@ -787,14 +769,14 @@ static int rc_validate_conflicting_conditions(const rc_condset_t* conditions, co
|
||||
if (compare_condition->type != condition_chain_iter->type ||
|
||||
compare_condition->oper != condition_chain_iter->oper ||
|
||||
compare_condition->required_hits != condition_chain_iter->required_hits ||
|
||||
!rc_validate_are_operands_equal(&compare_condition->operand1, &condition_chain_iter->operand1))
|
||||
!rc_operands_are_equal(&compare_condition->operand1, &condition_chain_iter->operand1))
|
||||
{
|
||||
chain_matches = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (compare_condition->oper != RC_OPERATOR_NONE &&
|
||||
!rc_validate_are_operands_equal(&compare_condition->operand2, &condition_chain_iter->operand2))
|
||||
!rc_operands_are_equal(&compare_condition->operand2, &condition_chain_iter->operand2))
|
||||
{
|
||||
chain_matches = 0;
|
||||
break;
|
||||
|
||||
@@ -7,13 +7,9 @@
|
||||
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
int rc_validate_memrefs(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t max_address);
|
||||
|
||||
int rc_validate_condset(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t max_address);
|
||||
int rc_validate_trigger(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t max_address);
|
||||
|
||||
int rc_validate_memrefs_for_console(const rc_memref_t* memref, char result[], const size_t result_size, uint32_t console_id);
|
||||
|
||||
int rc_validate_condset_for_console(const rc_condset_t* condset, char result[], const size_t result_size, uint32_t console_id);
|
||||
int rc_validate_trigger_for_console(const rc_trigger_t* trigger, char result[], const size_t result_size, uint32_t console_id);
|
||||
|
||||
|
||||
@@ -13,29 +13,67 @@ enum {
|
||||
RC_FORMAT_UNICODECHAR = 105
|
||||
};
|
||||
|
||||
static rc_memref_value_t* rc_alloc_helper_variable_memref_value(const char* memaddr, int memaddr_len, rc_parse_state_t* parse) {
|
||||
const char* end;
|
||||
rc_value_t* variable;
|
||||
uint32_t address;
|
||||
uint8_t size;
|
||||
static void rc_alloc_helper_variable_memref_value(rc_richpresence_display_part_t* part, const char* memaddr, int memaddr_len, rc_parse_state_t* parse) {
|
||||
rc_preparse_state_t preparse;
|
||||
const char* test_memaddr = memaddr;
|
||||
rc_condset_t* condset;
|
||||
rc_value_t* value;
|
||||
int32_t size;
|
||||
|
||||
/* single memory reference lookups without a modifier flag can be handled without a variable */
|
||||
end = memaddr;
|
||||
if (rc_parse_memref(&end, &size, &address) == RC_OK) {
|
||||
/* make sure the entire memaddr was consumed. if not, there's an operator and it's a comparison, not a memory reference */
|
||||
if (end == &memaddr[memaddr_len]) {
|
||||
/* if it's not a derived size, we can reference the memref directly */
|
||||
if (rc_memref_shared_size(size) == size)
|
||||
return &rc_alloc_memref(parse, address, size, 0)->value;
|
||||
part->value.type = RC_OPERAND_NONE;
|
||||
|
||||
/* if the expression can be represented as just a memory reference, do so */
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
preparse.parse.existing_memrefs = parse->memrefs;
|
||||
value = RC_ALLOC(rc_value_t, &preparse.parse);
|
||||
rc_parse_value_internal(value, &test_memaddr, &preparse.parse);
|
||||
|
||||
size = preparse.parse.offset;
|
||||
if (size < 0) {
|
||||
parse->offset = size;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ensure new needed memrefs are allocated in the primary buffer */
|
||||
rc_preparse_copy_memrefs(parse, &preparse.memrefs);
|
||||
|
||||
/* parse the value into the scratch buffer so we can look at it */
|
||||
rc_reset_parse_state(&preparse.parse, rc_buffer_alloc(&preparse.parse.scratch.buffer, (size_t)size), NULL, 0);
|
||||
preparse.parse.memrefs = parse->memrefs;
|
||||
preparse.parse.existing_memrefs = parse->existing_memrefs;
|
||||
value = RC_ALLOC(rc_value_t, &preparse.parse);
|
||||
test_memaddr = memaddr;
|
||||
rc_parse_value_internal(value, &test_memaddr, &preparse.parse);
|
||||
|
||||
condset = value->conditions;
|
||||
if (condset && !condset->next) {
|
||||
/* single value - if it's only "measured" and "indirect" conditions, we can simplify to a memref */
|
||||
if (condset->num_measured_conditions &&
|
||||
!condset->num_pause_conditions && !condset->num_reset_conditions &&
|
||||
!condset->num_other_conditions && !condset->num_hittarget_conditions) {
|
||||
rc_condition_t* condition = condset->conditions;
|
||||
for (; condition; condition = condition->next) {
|
||||
if (condition->type == RC_CONDITION_MEASURED && condition->required_hits == 0) {
|
||||
memcpy(&part->value, &condition->operand1, sizeof(condition->operand1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* not a simple memory reference, need to create a variable */
|
||||
variable = rc_alloc_helper_variable(memaddr, memaddr_len, parse);
|
||||
if (!variable)
|
||||
return NULL;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
|
||||
return &variable->value;
|
||||
/* could not express value with just a memory reference, create a helper variable */
|
||||
if (part->value.type == RC_OPERAND_NONE) {
|
||||
value = rc_alloc_variable(memaddr, memaddr_len, parse);
|
||||
if (value) {
|
||||
part->value.value.memref = (rc_memref_t*)&value->value;
|
||||
part->value.type = RC_OPERAND_ADDRESS;
|
||||
part->value.size = RC_MEMSIZE_32_BITS;
|
||||
part->value.memref_access_type = RC_OPERAND_ADDRESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char* rc_parse_line(const char* line, const char** end, rc_parse_state_t* parse) {
|
||||
@@ -220,7 +258,7 @@ static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const c
|
||||
part->text = rc_alloc_str(parse, in, (int)(ptr - in));
|
||||
}
|
||||
else if (part->display_type != RC_FORMAT_UNKNOWN_MACRO) {
|
||||
part->value = rc_alloc_helper_variable_memref_value(line, (int)(ptr - line), parse);
|
||||
rc_alloc_helper_variable_memref_value(part, line, (int)(ptr - line), parse);
|
||||
if (parse->offset < 0)
|
||||
return 0;
|
||||
|
||||
@@ -468,6 +506,8 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
|
||||
int display_line = 0;
|
||||
int chars;
|
||||
|
||||
self->values = NULL;
|
||||
|
||||
/* special case for empty script to return 1 line read */
|
||||
if (!*script) {
|
||||
parse->lines_read = 1;
|
||||
@@ -558,11 +598,20 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
|
||||
*nextdisplay = rc_parse_richpresence_display_internal(ptr + 1, endline, parse, firstlookup);
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
|
||||
trigger = &((*nextdisplay)->trigger);
|
||||
rc_parse_trigger_internal(trigger, &line, parse);
|
||||
trigger->memrefs = 0;
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
|
||||
if (line != ptr) {
|
||||
/* incomplete read */
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return;
|
||||
}
|
||||
|
||||
(*nextdisplay)->has_required_hits = parse->has_required_hits;
|
||||
|
||||
if (parse->buffer)
|
||||
nextdisplay = &((*nextdisplay)->next);
|
||||
}
|
||||
@@ -593,6 +642,7 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
|
||||
|
||||
/* finalize */
|
||||
*nextdisplay = 0;
|
||||
self->has_memrefs = 0;
|
||||
|
||||
if (!hasdisplay && parse->offset > 0) {
|
||||
parse->offset = RC_MISSING_DISPLAY_STRING;
|
||||
@@ -600,22 +650,20 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
|
||||
}
|
||||
|
||||
int rc_richpresence_size_lines(const char* script, int* lines_read) {
|
||||
rc_richpresence_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_memref_t* first_memref;
|
||||
rc_value_t* variables;
|
||||
rc_init_parse_state(&parse, 0, 0, 0);
|
||||
rc_init_parse_state_memrefs(&parse, &first_memref);
|
||||
rc_init_parse_state_variables(&parse, &variables);
|
||||
rc_richpresence_with_memrefs_t* richpresence;
|
||||
rc_preparse_state_t preparse;
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
|
||||
self = RC_ALLOC(rc_richpresence_t, &parse);
|
||||
rc_parse_richpresence_internal(self, script, &parse);
|
||||
richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse);
|
||||
preparse.parse.variables = &richpresence->richpresence.values;
|
||||
rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(NULL, &preparse);
|
||||
|
||||
if (lines_read)
|
||||
*lines_read = parse.lines_read;
|
||||
*lines_read = preparse.parse.lines_read;
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return parse.offset;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
int rc_richpresence_size(const char* script) {
|
||||
@@ -623,32 +671,53 @@ int rc_richpresence_size(const char* script) {
|
||||
}
|
||||
|
||||
rc_richpresence_t* rc_parse_richpresence(void* buffer, const char* script, lua_State* L, int funcs_ndx) {
|
||||
rc_richpresence_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_richpresence_with_memrefs_t* richpresence;
|
||||
rc_preparse_state_t preparse;
|
||||
|
||||
if (!buffer || !script)
|
||||
return NULL;
|
||||
|
||||
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
|
||||
rc_init_preparse_state(&preparse, L, funcs_ndx);
|
||||
richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse);
|
||||
preparse.parse.variables = &richpresence->richpresence.values;
|
||||
rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse);
|
||||
|
||||
self = RC_ALLOC(rc_richpresence_t, &parse);
|
||||
rc_init_parse_state_memrefs(&parse, &self->memrefs);
|
||||
rc_init_parse_state_variables(&parse, &self->variables);
|
||||
rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx);
|
||||
richpresence = RC_ALLOC(rc_richpresence_with_memrefs_t, &preparse.parse);
|
||||
preparse.parse.variables = &richpresence->richpresence.values;
|
||||
rc_preparse_alloc_memrefs(&richpresence->memrefs, &preparse);
|
||||
|
||||
rc_parse_richpresence_internal(self, script, &parse);
|
||||
rc_parse_richpresence_internal(&richpresence->richpresence, script, &preparse.parse);
|
||||
richpresence->richpresence.has_memrefs = 1;
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return (parse.offset >= 0) ? self : NULL;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return (preparse.parse.offset >= 0) ? &richpresence->richpresence : NULL;
|
||||
}
|
||||
|
||||
static void rc_update_richpresence_memrefs(rc_richpresence_t* self, rc_peek_t peek, void* ud) {
|
||||
if (self->has_memrefs) {
|
||||
rc_richpresence_with_memrefs_t* richpresence = (rc_richpresence_with_memrefs_t*)self;
|
||||
rc_update_memref_values(&richpresence->memrefs, peek, ud);
|
||||
}
|
||||
}
|
||||
|
||||
rc_memrefs_t* rc_richpresence_get_memrefs(rc_richpresence_t* self) {
|
||||
if (self->has_memrefs) {
|
||||
rc_richpresence_with_memrefs_t* richpresence = (rc_richpresence_with_memrefs_t*)self;
|
||||
return &richpresence->memrefs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rc_update_richpresence(rc_richpresence_t* richpresence, rc_peek_t peek, void* peek_ud, lua_State* L) {
|
||||
rc_richpresence_display_t* display;
|
||||
|
||||
rc_update_memref_values(richpresence->memrefs, peek, peek_ud);
|
||||
rc_update_variables(richpresence->variables, peek, peek_ud, L);
|
||||
rc_update_richpresence_memrefs(richpresence, peek, peek_ud);
|
||||
rc_update_values(richpresence->values, peek, peek_ud, L);
|
||||
|
||||
for (display = richpresence->first_display; display; display = display->next) {
|
||||
if (display->trigger.has_required_hits)
|
||||
if (display->has_required_hits)
|
||||
rc_test_trigger(&display->trigger, peek, peek_ud, L);
|
||||
}
|
||||
}
|
||||
@@ -671,7 +740,7 @@ static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part
|
||||
break;
|
||||
|
||||
case RC_FORMAT_LOOKUP:
|
||||
rc_typed_value_from_memref_value(&value, part->value);
|
||||
rc_evaluate_operand(&value, &part->value, NULL);
|
||||
rc_typed_value_convert(&value, RC_VALUE_TYPE_UNSIGNED);
|
||||
|
||||
text = part->lookup->default_label;
|
||||
@@ -698,7 +767,7 @@ static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part
|
||||
value.type = RC_VALUE_TYPE_UNSIGNED;
|
||||
|
||||
do {
|
||||
value.value.u32 = part->value->value;
|
||||
rc_evaluate_operand(&value, &part->value, NULL);
|
||||
if (value.value.u32 == 0) {
|
||||
/* null terminator - skip over remaining character macros */
|
||||
while (part->next && part->next->display_type == RC_FORMAT_ASCIICHAR)
|
||||
@@ -725,7 +794,7 @@ static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part
|
||||
value.type = RC_VALUE_TYPE_UNSIGNED;
|
||||
|
||||
do {
|
||||
value.value.u32 = part->value->value;
|
||||
rc_evaluate_operand(&value, &part->value, NULL);
|
||||
if (value.value.u32 == 0) {
|
||||
/* null terminator - skip over remaining character macros */
|
||||
while (part->next && part->next->display_type == RC_FORMAT_UNICODECHAR)
|
||||
@@ -770,7 +839,7 @@ static int rc_evaluate_richpresence_display(rc_richpresence_display_part_t* part
|
||||
break;
|
||||
|
||||
default:
|
||||
rc_typed_value_from_memref_value(&value, part->value);
|
||||
rc_evaluate_operand(&value, &part->value, NULL);
|
||||
chars = rc_format_typed_value(tmp, sizeof(tmp), &value, part->display_type);
|
||||
text = tmp;
|
||||
break;
|
||||
@@ -806,7 +875,7 @@ int rc_get_richpresence_display_string(rc_richpresence_t* richpresence, char* bu
|
||||
return rc_evaluate_richpresence_display(display->display, buffer, buffersize);
|
||||
|
||||
/* triggers with required hits will be updated in rc_update_richpresence */
|
||||
if (!display->trigger.has_required_hits)
|
||||
if (!display->has_required_hits)
|
||||
rc_test_trigger(&display->trigger, peek, peek_ud, L);
|
||||
|
||||
/* if we've found a valid condition, process it */
|
||||
@@ -823,15 +892,16 @@ int rc_evaluate_richpresence(rc_richpresence_t* richpresence, char* buffer, size
|
||||
return rc_get_richpresence_display_string(richpresence, buffer, buffersize, peek, peek_ud, L);
|
||||
}
|
||||
|
||||
void rc_reset_richpresence(rc_richpresence_t* self) {
|
||||
void rc_reset_richpresence_triggers(rc_richpresence_t* self) {
|
||||
rc_richpresence_display_t* display;
|
||||
rc_value_t* variable;
|
||||
|
||||
for (display = self->first_display; display; display = display->next)
|
||||
rc_reset_trigger(&display->trigger);
|
||||
}
|
||||
|
||||
for (variable = self->variables; variable; variable = variable->next)
|
||||
rc_reset_value(variable);
|
||||
void rc_reset_richpresence(rc_richpresence_t* self) {
|
||||
rc_reset_richpresence_triggers(self);
|
||||
rc_reset_values(self->values);
|
||||
}
|
||||
|
||||
static int rc_get_richpresence_strings_has_string(const char** buffer, size_t written, const char* search) {
|
||||
|
||||
@@ -9,8 +9,34 @@
|
||||
|
||||
#define RC_RICHPRESENCE_DISPLAY_BUFFER_SIZE 256
|
||||
|
||||
/* ===== natvis extensions ===== */
|
||||
|
||||
typedef struct __rc_runtime_trigger_list_t { rc_runtime_t runtime; } __rc_runtime_trigger_list_t;
|
||||
typedef struct __rc_runtime_lboard_list_t { rc_runtime_t runtime; } __rc_runtime_lboard_list_t;
|
||||
|
||||
static void rc_runtime_natvis_helper(const rc_runtime_event_t* runtime_event)
|
||||
{
|
||||
struct natvis_extensions {
|
||||
__rc_runtime_trigger_list_t trigger_list;
|
||||
__rc_runtime_lboard_list_t lboard_list;
|
||||
} natvis;
|
||||
|
||||
memset(&natvis, 0, sizeof(natvis));
|
||||
(void)runtime_event;
|
||||
|
||||
natvis.lboard_list.runtime.lboard_count = 0;
|
||||
}
|
||||
|
||||
/* ============================= */
|
||||
|
||||
rc_runtime_t* rc_runtime_alloc(void) {
|
||||
rc_runtime_t* self = malloc(sizeof(rc_runtime_t));
|
||||
rc_runtime_t* self;
|
||||
|
||||
/* create a reference to rc_runtime_natvis_helper so the extensions get compiled in. */
|
||||
rc_runtime_event_handler_t unused = &rc_runtime_natvis_helper;
|
||||
(void)unused;
|
||||
|
||||
self = malloc(sizeof(rc_runtime_t));
|
||||
|
||||
if (self) {
|
||||
rc_runtime_init(self);
|
||||
@@ -22,16 +48,19 @@ rc_runtime_t* rc_runtime_alloc(void) {
|
||||
|
||||
void rc_runtime_init(rc_runtime_t* self) {
|
||||
memset(self, 0, sizeof(rc_runtime_t));
|
||||
self->next_memref = &self->memrefs;
|
||||
self->next_variable = &self->variables;
|
||||
|
||||
self->memrefs = (rc_memrefs_t*)malloc(sizeof(*self->memrefs));
|
||||
rc_memrefs_init(self->memrefs);
|
||||
}
|
||||
|
||||
void rc_runtime_destroy(rc_runtime_t* self) {
|
||||
uint32_t i;
|
||||
|
||||
if (self->triggers) {
|
||||
for (i = 0; i < self->trigger_count; ++i)
|
||||
free(self->triggers[i].buffer);
|
||||
for (i = 0; i < self->trigger_count; ++i) {
|
||||
if (self->triggers[i].buffer)
|
||||
free(self->triggers[i].buffer);
|
||||
}
|
||||
|
||||
free(self->triggers);
|
||||
self->triggers = NULL;
|
||||
@@ -40,8 +69,10 @@ void rc_runtime_destroy(rc_runtime_t* self) {
|
||||
}
|
||||
|
||||
if (self->lboards) {
|
||||
for (i = 0; i < self->lboard_count; ++i)
|
||||
free(self->lboards[i].buffer);
|
||||
for (i = 0; i < self->lboard_count; ++i) {
|
||||
if (self->lboards[i].buffer)
|
||||
free(self->lboards[i].buffer);
|
||||
}
|
||||
|
||||
free(self->lboards);
|
||||
self->lboards = NULL;
|
||||
@@ -49,20 +80,17 @@ void rc_runtime_destroy(rc_runtime_t* self) {
|
||||
self->lboard_count = self->lboard_capacity = 0;
|
||||
}
|
||||
|
||||
while (self->richpresence) {
|
||||
rc_runtime_richpresence_t* previous = self->richpresence->previous;
|
||||
|
||||
free(self->richpresence->buffer);
|
||||
if (self->richpresence) {
|
||||
if (self->richpresence->buffer)
|
||||
free(self->richpresence->buffer);
|
||||
free(self->richpresence);
|
||||
self->richpresence = previous;
|
||||
}
|
||||
|
||||
self->next_memref = 0;
|
||||
self->memrefs = 0;
|
||||
if (self->memrefs)
|
||||
rc_memrefs_destroy(self->memrefs);
|
||||
|
||||
if (self->owns_self) {
|
||||
if (self->owns_self)
|
||||
free(self);
|
||||
}
|
||||
}
|
||||
|
||||
void rc_runtime_checksum(const char* memaddr, uint8_t* md5) {
|
||||
@@ -72,45 +100,12 @@ void rc_runtime_checksum(const char* memaddr, uint8_t* md5) {
|
||||
md5_finish(&state, md5);
|
||||
}
|
||||
|
||||
static char rc_runtime_allocated_memrefs(rc_runtime_t* self) {
|
||||
char owns_memref = 0;
|
||||
|
||||
/* if at least one memref was allocated within the object, we can't free the buffer when the object is deactivated */
|
||||
if (*self->next_memref != NULL) {
|
||||
owns_memref = 1;
|
||||
/* advance through the new memrefs so we're ready for the next allocation */
|
||||
do {
|
||||
self->next_memref = &(*self->next_memref)->next;
|
||||
} while (*self->next_memref != NULL);
|
||||
}
|
||||
|
||||
/* if at least one variable was allocated within the object, we can't free the buffer when the object is deactivated */
|
||||
if (*self->next_variable != NULL) {
|
||||
owns_memref = 1;
|
||||
/* advance through the new variables so we're ready for the next allocation */
|
||||
do {
|
||||
self->next_variable = &(*self->next_variable)->next;
|
||||
} while (*self->next_variable != NULL);
|
||||
}
|
||||
|
||||
return owns_memref;
|
||||
}
|
||||
|
||||
static void rc_runtime_deactivate_trigger_by_index(rc_runtime_t* self, uint32_t index) {
|
||||
if (self->triggers[index].owns_memrefs) {
|
||||
/* if the trigger has one or more memrefs in its buffer, we can't free the buffer.
|
||||
* just null out the trigger so the runtime processor will skip it
|
||||
*/
|
||||
rc_reset_trigger(self->triggers[index].trigger);
|
||||
self->triggers[index].trigger = NULL;
|
||||
}
|
||||
else {
|
||||
/* trigger doesn't own any memrefs, go ahead and free it, then replace it with the last trigger */
|
||||
free(self->triggers[index].buffer);
|
||||
/* free the trigger, then replace it with the last trigger */
|
||||
free(self->triggers[index].buffer);
|
||||
|
||||
if (--self->trigger_count > index)
|
||||
memcpy(&self->triggers[index], &self->triggers[self->trigger_count], sizeof(rc_runtime_trigger_t));
|
||||
}
|
||||
if (--self->trigger_count > index)
|
||||
memcpy(&self->triggers[index], &self->triggers[self->trigger_count], sizeof(rc_runtime_trigger_t));
|
||||
}
|
||||
|
||||
void rc_runtime_deactivate_achievement(rc_runtime_t* self, uint32_t id) {
|
||||
@@ -126,7 +121,8 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char*
|
||||
void* trigger_buffer;
|
||||
rc_trigger_t* trigger;
|
||||
rc_runtime_trigger_t* runtime_trigger;
|
||||
rc_parse_state_t parse;
|
||||
rc_preparse_state_t preparse;
|
||||
const char* preparse_memaddr = memaddr;
|
||||
uint8_t md5[16];
|
||||
int32_t size;
|
||||
uint32_t i;
|
||||
@@ -169,7 +165,12 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char*
|
||||
}
|
||||
|
||||
/* item has not been previously registered, determine how much space we need for it, and allocate it */
|
||||
size = rc_trigger_size(memaddr);
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
preparse.parse.existing_memrefs = self->memrefs;
|
||||
trigger = RC_ALLOC(rc_trigger_t, &preparse.parse);
|
||||
rc_parse_trigger_internal(trigger, &preparse_memaddr, &preparse.parse);
|
||||
|
||||
size = preparse.parse.offset;
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
@@ -178,16 +179,15 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char*
|
||||
return RC_OUT_OF_MEMORY;
|
||||
|
||||
/* populate the item, using the communal memrefs pool */
|
||||
rc_init_parse_state(&parse, trigger_buffer, L, funcs_idx);
|
||||
parse.first_memref = &self->memrefs;
|
||||
trigger = RC_ALLOC(rc_trigger_t, &parse);
|
||||
rc_parse_trigger_internal(trigger, &memaddr, &parse);
|
||||
rc_destroy_parse_state(&parse);
|
||||
rc_reset_parse_state(&preparse.parse, trigger_buffer, L, funcs_idx);
|
||||
rc_preparse_reserve_memrefs(&preparse, self->memrefs);
|
||||
trigger = RC_ALLOC(rc_trigger_t, &preparse.parse);
|
||||
rc_parse_trigger_internal(trigger, &memaddr, &preparse.parse);
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
|
||||
if (parse.offset < 0) {
|
||||
if (preparse.parse.offset < 0) {
|
||||
free(trigger_buffer);
|
||||
*self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */
|
||||
return parse.offset;
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
/* grow the trigger buffer if necessary */
|
||||
@@ -200,7 +200,6 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char*
|
||||
|
||||
if (!self->triggers) {
|
||||
free(trigger_buffer);
|
||||
*self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */
|
||||
return RC_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -213,11 +212,9 @@ int rc_runtime_activate_achievement(rc_runtime_t* self, uint32_t id, const char*
|
||||
runtime_trigger->invalid_memref = NULL;
|
||||
memcpy(runtime_trigger->md5, md5, 16);
|
||||
runtime_trigger->serialized_size = 0;
|
||||
runtime_trigger->owns_memrefs = rc_runtime_allocated_memrefs(self);
|
||||
++self->trigger_count;
|
||||
|
||||
/* reset it, and return it */
|
||||
trigger->memrefs = NULL;
|
||||
rc_reset_trigger(trigger);
|
||||
return RC_OK;
|
||||
}
|
||||
@@ -285,20 +282,11 @@ int rc_runtime_format_achievement_measured(const rc_runtime_t* runtime, uint32_t
|
||||
}
|
||||
|
||||
static void rc_runtime_deactivate_lboard_by_index(rc_runtime_t* self, uint32_t index) {
|
||||
if (self->lboards[index].owns_memrefs) {
|
||||
/* if the lboard has one or more memrefs in its buffer, we can't free the buffer.
|
||||
* just null out the lboard so the runtime processor will skip it
|
||||
*/
|
||||
rc_reset_lboard(self->lboards[index].lboard);
|
||||
self->lboards[index].lboard = NULL;
|
||||
}
|
||||
else {
|
||||
/* lboard doesn't own any memrefs, go ahead and free it, then replace it with the last lboard */
|
||||
free(self->lboards[index].buffer);
|
||||
/* free the lboard, then replace it with the last lboard */
|
||||
free(self->lboards[index].buffer);
|
||||
|
||||
if (--self->lboard_count > index)
|
||||
memcpy(&self->lboards[index], &self->lboards[self->lboard_count], sizeof(rc_runtime_lboard_t));
|
||||
}
|
||||
if (--self->lboard_count > index)
|
||||
memcpy(&self->lboards[index], &self->lboards[self->lboard_count], sizeof(rc_runtime_lboard_t));
|
||||
}
|
||||
|
||||
void rc_runtime_deactivate_lboard(rc_runtime_t* self, uint32_t id) {
|
||||
@@ -314,7 +302,7 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
void* lboard_buffer;
|
||||
uint8_t md5[16];
|
||||
rc_lboard_t* lboard;
|
||||
rc_parse_state_t parse;
|
||||
rc_preparse_state_t preparse;
|
||||
rc_runtime_lboard_t* runtime_lboard;
|
||||
int size;
|
||||
uint32_t i;
|
||||
@@ -357,7 +345,12 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
}
|
||||
|
||||
/* item has not been previously registered, determine how much space we need for it, and allocate it */
|
||||
size = rc_lboard_size(memaddr);
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
preparse.parse.existing_memrefs = self->memrefs;
|
||||
lboard = RC_ALLOC(rc_lboard_t, &preparse.parse);
|
||||
rc_parse_lboard_internal(lboard, memaddr, &preparse.parse);
|
||||
|
||||
size = preparse.parse.offset;
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
@@ -366,16 +359,15 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
return RC_OUT_OF_MEMORY;
|
||||
|
||||
/* populate the item, using the communal memrefs pool */
|
||||
rc_init_parse_state(&parse, lboard_buffer, L, funcs_idx);
|
||||
lboard = RC_ALLOC(rc_lboard_t, &parse);
|
||||
parse.first_memref = &self->memrefs;
|
||||
rc_parse_lboard_internal(lboard, memaddr, &parse);
|
||||
rc_destroy_parse_state(&parse);
|
||||
rc_reset_parse_state(&preparse.parse, lboard_buffer, L, funcs_idx);
|
||||
rc_preparse_reserve_memrefs(&preparse, self->memrefs);
|
||||
lboard = RC_ALLOC(rc_lboard_t, &preparse.parse);
|
||||
rc_parse_lboard_internal(lboard, memaddr, &preparse.parse);
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
|
||||
if (parse.offset < 0) {
|
||||
if (preparse.parse.offset < 0) {
|
||||
free(lboard_buffer);
|
||||
*self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */
|
||||
return parse.offset;
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
/* grow the lboard buffer if necessary */
|
||||
@@ -388,7 +380,6 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
|
||||
if (!self->lboards) {
|
||||
free(lboard_buffer);
|
||||
*self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */
|
||||
return RC_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -402,10 +393,8 @@ int rc_runtime_activate_lboard(rc_runtime_t* self, uint32_t id, const char* mema
|
||||
runtime_lboard->invalid_memref = NULL;
|
||||
memcpy(runtime_lboard->md5, md5, 16);
|
||||
runtime_lboard->serialized_size = 0;
|
||||
runtime_lboard->owns_memrefs = rc_runtime_allocated_memrefs(self);
|
||||
|
||||
/* reset it, and return it */
|
||||
lboard->memrefs = NULL;
|
||||
rc_reset_lboard(lboard);
|
||||
return RC_OK;
|
||||
}
|
||||
@@ -429,9 +418,7 @@ int rc_runtime_format_lboard_value(char* buffer, int size, int32_t value, int fo
|
||||
|
||||
int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua_State* L, int funcs_idx) {
|
||||
rc_richpresence_t* richpresence;
|
||||
rc_runtime_richpresence_t* previous;
|
||||
rc_runtime_richpresence_t** previous_ptr;
|
||||
rc_parse_state_t parse;
|
||||
rc_preparse_state_t preparse;
|
||||
uint8_t md5[16];
|
||||
int size;
|
||||
|
||||
@@ -441,47 +428,29 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua
|
||||
rc_runtime_checksum(script, md5);
|
||||
|
||||
/* look for existing match */
|
||||
previous_ptr = NULL;
|
||||
previous = self->richpresence;
|
||||
while (previous) {
|
||||
if (previous && self->richpresence->richpresence && memcmp(self->richpresence->md5, md5, 16) == 0) {
|
||||
/* unchanged. reset all of the conditions */
|
||||
rc_reset_richpresence(self->richpresence->richpresence);
|
||||
if (self->richpresence && self->richpresence->richpresence && memcmp(self->richpresence->md5, md5, 16) == 0) {
|
||||
/* unchanged. reset all of the conditions */
|
||||
rc_reset_richpresence(self->richpresence->richpresence);
|
||||
|
||||
/* move to front of linked list*/
|
||||
if (previous_ptr) {
|
||||
*previous_ptr = previous->previous;
|
||||
if (!self->richpresence->owns_memrefs) {
|
||||
free(self->richpresence->buffer);
|
||||
previous->previous = self->richpresence->previous;
|
||||
}
|
||||
else {
|
||||
previous->previous = self->richpresence;
|
||||
}
|
||||
|
||||
self->richpresence = previous;
|
||||
}
|
||||
|
||||
/* return success*/
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
previous_ptr = &previous->previous;
|
||||
previous = previous->previous;
|
||||
/* return success*/
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
/* no existing match found, parse script */
|
||||
size = rc_richpresence_size(script);
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
preparse.parse.existing_memrefs = self->memrefs;
|
||||
richpresence = RC_ALLOC(rc_richpresence_t, &preparse.parse);
|
||||
preparse.parse.variables = &richpresence->values;
|
||||
rc_parse_richpresence_internal(richpresence, script, &preparse.parse);
|
||||
|
||||
size = preparse.parse.offset;
|
||||
if (size < 0)
|
||||
return size;
|
||||
|
||||
/* if the previous script doesn't have any memrefs, free it */
|
||||
previous = self->richpresence;
|
||||
if (previous) {
|
||||
if (!previous->owns_memrefs) {
|
||||
free(previous->buffer);
|
||||
previous = previous->previous;
|
||||
}
|
||||
/* if there's a previous script, free it */
|
||||
if (self->richpresence) {
|
||||
free(self->richpresence->buffer);
|
||||
free(self->richpresence);
|
||||
}
|
||||
|
||||
/* allocate and process the new script */
|
||||
@@ -489,34 +458,26 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua
|
||||
if (!self->richpresence)
|
||||
return RC_OUT_OF_MEMORY;
|
||||
|
||||
self->richpresence->previous = previous;
|
||||
self->richpresence->owns_memrefs = 0;
|
||||
memcpy(self->richpresence->md5, md5, sizeof(md5));
|
||||
self->richpresence->buffer = malloc(size);
|
||||
|
||||
self->richpresence->buffer = malloc(size);
|
||||
if (!self->richpresence->buffer)
|
||||
return RC_OUT_OF_MEMORY;
|
||||
|
||||
rc_init_parse_state(&parse, self->richpresence->buffer, L, funcs_idx);
|
||||
self->richpresence->richpresence = richpresence = RC_ALLOC(rc_richpresence_t, &parse);
|
||||
parse.first_memref = &self->memrefs;
|
||||
parse.variables = &self->variables;
|
||||
rc_parse_richpresence_internal(richpresence, script, &parse);
|
||||
rc_destroy_parse_state(&parse);
|
||||
rc_reset_parse_state(&preparse.parse, self->richpresence->buffer, L, funcs_idx);
|
||||
rc_preparse_reserve_memrefs(&preparse, self->memrefs);
|
||||
richpresence = RC_ALLOC(rc_richpresence_t, &preparse.parse);
|
||||
preparse.parse.variables = &richpresence->values;
|
||||
rc_parse_richpresence_internal(richpresence, script, &preparse.parse);
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
|
||||
if (parse.offset < 0) {
|
||||
if (preparse.parse.offset < 0) {
|
||||
free(self->richpresence->buffer);
|
||||
free(self->richpresence);
|
||||
self->richpresence = previous;
|
||||
*self->next_memref = NULL; /* disassociate any memrefs allocated by the failed parse */
|
||||
return parse.offset;
|
||||
self->richpresence = NULL;
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
self->richpresence->owns_memrefs = rc_runtime_allocated_memrefs(self);
|
||||
|
||||
richpresence->memrefs = NULL;
|
||||
richpresence->variables = NULL;
|
||||
|
||||
if (!richpresence->first_display || !richpresence->first_display->display) {
|
||||
/* non-existant rich presence */
|
||||
self->richpresence->richpresence = NULL;
|
||||
@@ -524,6 +485,7 @@ int rc_runtime_activate_richpresence(rc_runtime_t* self, const char* script, lua
|
||||
else {
|
||||
/* reset all of the conditions */
|
||||
rc_reset_richpresence(richpresence);
|
||||
self->richpresence->richpresence = richpresence;
|
||||
}
|
||||
|
||||
return RC_OK;
|
||||
@@ -555,7 +517,6 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
|
||||
runtime_event.value = 0;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
rc_update_variables(self->variables, peek, ud, L);
|
||||
|
||||
for (i = self->trigger_count - 1; i >= 0; --i) {
|
||||
rc_trigger_t* trigger = self->triggers[i].trigger;
|
||||
@@ -725,7 +686,6 @@ void rc_runtime_do_frame(rc_runtime_t* self, rc_runtime_event_handler_t event_ha
|
||||
}
|
||||
|
||||
void rc_runtime_reset(rc_runtime_t* self) {
|
||||
rc_value_t* variable;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < self->trigger_count; ++i) {
|
||||
@@ -740,9 +700,6 @@ void rc_runtime_reset(rc_runtime_t* self) {
|
||||
|
||||
if (self->richpresence && self->richpresence->richpresence)
|
||||
rc_reset_richpresence(self->richpresence->richpresence);
|
||||
|
||||
for (variable = self->variables; variable; variable = variable->next)
|
||||
rc_reset_value(variable);
|
||||
}
|
||||
|
||||
static int rc_condset_contains_memref(const rc_condset_t* condset, const rc_memref_t* memref) {
|
||||
@@ -826,47 +783,41 @@ static void rc_runtime_invalidate_memref(rc_runtime_t* self, rc_memref_t* memref
|
||||
}
|
||||
|
||||
void rc_runtime_invalidate_address(rc_runtime_t* self, uint32_t address) {
|
||||
rc_memref_t** last_memref = &self->memrefs;
|
||||
rc_memref_t* memref = self->memrefs;
|
||||
rc_memref_list_t* memref_list = &self->memrefs->memrefs;
|
||||
do {
|
||||
rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_stop = memref + memref_list->count;
|
||||
|
||||
while (memref) {
|
||||
if (memref->address == address && !memref->value.is_indirect) {
|
||||
/* remove the invalid memref from the chain so we don't try to evaluate it in the future.
|
||||
* it's still there, so anything referencing it will continue to fetch 0.
|
||||
*/
|
||||
*last_memref = memref->next;
|
||||
|
||||
rc_runtime_invalidate_memref(self, memref);
|
||||
break;
|
||||
for (; memref < memref_stop; ++memref) {
|
||||
if (memref->address == address) {
|
||||
memref->value.type = RC_VALUE_TYPE_NONE;
|
||||
rc_runtime_invalidate_memref(self, memref);
|
||||
}
|
||||
}
|
||||
|
||||
last_memref = &memref->next;
|
||||
memref = *last_memref;
|
||||
}
|
||||
memref_list = memref_list->next;
|
||||
} while (memref_list);
|
||||
}
|
||||
|
||||
void rc_runtime_validate_addresses(rc_runtime_t* self, rc_runtime_event_handler_t event_handler,
|
||||
rc_runtime_validate_address_t validate_handler) {
|
||||
rc_memref_t** last_memref = &self->memrefs;
|
||||
rc_memref_t* memref = self->memrefs;
|
||||
int num_invalid = 0;
|
||||
rc_memref_list_t* memref_list = &self->memrefs->memrefs;
|
||||
do {
|
||||
rc_memref_t* memref = memref_list->items;
|
||||
const rc_memref_t* memref_stop = memref + memref_list->count;
|
||||
|
||||
while (memref) {
|
||||
if (!memref->value.is_indirect && !validate_handler(memref->address)) {
|
||||
/* remove the invalid memref from the chain so we don't try to evaluate it in the future.
|
||||
* it's still there, so anything referencing it will continue to fetch 0.
|
||||
*/
|
||||
*last_memref = memref->next;
|
||||
for (; memref < memref_stop; ++memref) {
|
||||
if (!validate_handler(memref->address)) {
|
||||
memref->value.type = RC_VALUE_TYPE_NONE;
|
||||
rc_runtime_invalidate_memref(self, memref);
|
||||
|
||||
rc_runtime_invalidate_memref(self, memref);
|
||||
++num_invalid;
|
||||
}
|
||||
else {
|
||||
last_memref = &memref->next;
|
||||
++num_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
memref = *last_memref;
|
||||
}
|
||||
memref_list = memref_list->next;
|
||||
} while (memref_list);
|
||||
|
||||
if (num_invalid) {
|
||||
rc_runtime_event_t runtime_event;
|
||||
|
||||
@@ -127,11 +127,7 @@ static void rc_runtime_progress_init(rc_runtime_progress_t* progress, const rc_r
|
||||
|
||||
static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress)
|
||||
{
|
||||
rc_memref_t* memref;
|
||||
uint32_t count = 0;
|
||||
|
||||
for (memref = progress->runtime->memrefs; memref; memref = memref->next)
|
||||
++count;
|
||||
uint32_t count = rc_memrefs_count_memrefs(progress->runtime->memrefs);
|
||||
if (count == 0)
|
||||
return RC_OK;
|
||||
|
||||
@@ -145,15 +141,24 @@ static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress)
|
||||
}
|
||||
else {
|
||||
uint32_t flags = 0;
|
||||
for (memref = progress->runtime->memrefs; memref; memref = memref->next) {
|
||||
flags = memref->value.size;
|
||||
if (memref->value.changed)
|
||||
flags |= RC_MEMREF_FLAG_CHANGED_THIS_FRAME;
|
||||
const rc_memref_list_t* memref_list = &progress->runtime->memrefs->memrefs;
|
||||
const rc_memref_t* memref;
|
||||
|
||||
rc_runtime_progress_write_uint(progress, memref->address);
|
||||
rc_runtime_progress_write_uint(progress, flags);
|
||||
rc_runtime_progress_write_uint(progress, memref->value.value);
|
||||
rc_runtime_progress_write_uint(progress, memref->value.prior);
|
||||
for (; memref_list; memref_list = memref_list->next) {
|
||||
const rc_memref_t* memref_end;
|
||||
|
||||
memref = memref_list->items;
|
||||
memref_end = memref + memref_list->count;
|
||||
for (; memref < memref_end; ++memref) {
|
||||
flags = memref->value.size;
|
||||
if (memref->value.changed)
|
||||
flags |= RC_MEMREF_FLAG_CHANGED_THIS_FRAME;
|
||||
|
||||
rc_runtime_progress_write_uint(progress, memref->address);
|
||||
rc_runtime_progress_write_uint(progress, flags);
|
||||
rc_runtime_progress_write_uint(progress, memref->value.value);
|
||||
rc_runtime_progress_write_uint(progress, memref->value.prior);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,13 +167,77 @@ static int rc_runtime_progress_write_memrefs(rc_runtime_progress_t* progress)
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
static void rc_runtime_progress_update_modified_memrefs(rc_runtime_progress_t* progress)
|
||||
{
|
||||
rc_typed_value_t value, prior_value, modifier, prior_modifier;
|
||||
rc_modified_memref_list_t* modified_memref_list;
|
||||
rc_modified_memref_t* modified_memref;
|
||||
rc_operand_t prior_parent_operand, prior_modifier_operand;
|
||||
rc_memref_t prior_parent_memref, prior_modifier_memref;
|
||||
|
||||
modified_memref_list = &progress->runtime->memrefs->modified_memrefs;
|
||||
for (; modified_memref_list; modified_memref_list = modified_memref_list->next) {
|
||||
const rc_modified_memref_t* modified_memref_end;
|
||||
modified_memref = modified_memref_list->items;
|
||||
modified_memref_end = modified_memref + modified_memref_list->count;
|
||||
for (; modified_memref < modified_memref_end; ++modified_memref) {
|
||||
modified_memref->memref.value.changed = 0;
|
||||
|
||||
/* indirect memref values are stored in conditions */
|
||||
if (modified_memref->modifier_type == RC_OPERATOR_INDIRECT_READ)
|
||||
continue;
|
||||
|
||||
/* non-indirect memref values can be reconstructed from the parents */
|
||||
memcpy(&prior_parent_operand, &modified_memref->parent, sizeof(prior_parent_operand));
|
||||
if (rc_operand_is_memref(&prior_parent_operand)) {
|
||||
memcpy(&prior_parent_memref, modified_memref->parent.value.memref, sizeof(prior_parent_memref));
|
||||
prior_parent_memref.value.value = prior_parent_memref.value.prior;
|
||||
modified_memref->memref.value.changed |= prior_parent_memref.value.changed;
|
||||
prior_parent_operand.value.memref = &prior_parent_memref;
|
||||
}
|
||||
|
||||
memcpy(&prior_modifier_operand, &modified_memref->modifier, sizeof(prior_modifier_operand));
|
||||
if (rc_operand_is_memref(&prior_modifier_operand)) {
|
||||
memcpy(&prior_modifier_memref, modified_memref->modifier.value.memref, sizeof(prior_modifier_memref));
|
||||
prior_modifier_memref.value.value = prior_modifier_memref.value.prior;
|
||||
modified_memref->memref.value.changed |= prior_modifier_memref.value.changed;
|
||||
prior_modifier_operand.value.memref = &prior_modifier_memref;
|
||||
}
|
||||
|
||||
rc_evaluate_operand(&value, &modified_memref->parent, NULL);
|
||||
rc_evaluate_operand(&modifier, &modified_memref->modifier, NULL);
|
||||
rc_evaluate_operand(&prior_value, &prior_parent_operand, NULL);
|
||||
rc_evaluate_operand(&prior_modifier, &prior_modifier_operand, NULL);
|
||||
|
||||
if (modified_memref->modifier_type == RC_OPERATOR_SUB_PARENT) {
|
||||
rc_typed_value_negate(&value);
|
||||
rc_typed_value_add(&value, &modifier);
|
||||
|
||||
rc_typed_value_negate(&prior_value);
|
||||
rc_typed_value_add(&prior_value, &prior_modifier);
|
||||
}
|
||||
else {
|
||||
rc_typed_value_combine(&value, &modifier, modified_memref->modifier_type);
|
||||
rc_typed_value_combine(&prior_value, &prior_modifier, modified_memref->modifier_type);
|
||||
}
|
||||
|
||||
rc_typed_value_convert(&value, modified_memref->memref.value.type);
|
||||
modified_memref->memref.value.value = value.value.u32;
|
||||
|
||||
rc_typed_value_convert(&prior_value, modified_memref->memref.value.type);
|
||||
modified_memref->memref.value.prior = prior_value.value.u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rc_runtime_progress_read_memrefs(rc_runtime_progress_t* progress)
|
||||
{
|
||||
uint32_t entries;
|
||||
uint32_t address, flags, value, prior;
|
||||
uint8_t size;
|
||||
rc_memref_list_t* unmatched_memref_list = &progress->runtime->memrefs->memrefs;
|
||||
rc_memref_t* first_unmatched_memref = unmatched_memref_list->items;
|
||||
rc_memref_t* memref;
|
||||
rc_memref_t* first_unmatched_memref = progress->runtime->memrefs;
|
||||
|
||||
/* re-read the chunk size to determine how many memrefs are present */
|
||||
progress->offset -= 4;
|
||||
@@ -183,24 +252,46 @@ static int rc_runtime_progress_read_memrefs(rc_runtime_progress_t* progress)
|
||||
size = flags & 0xFF;
|
||||
|
||||
memref = first_unmatched_memref;
|
||||
while (memref) {
|
||||
if (memref->address == address && memref->value.size == size) {
|
||||
memref->value.value = value;
|
||||
memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0;
|
||||
memref->value.prior = prior;
|
||||
if (memref->address == address && memref->value.size == size) {
|
||||
memref->value.value = value;
|
||||
memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0;
|
||||
memref->value.prior = prior;
|
||||
|
||||
if (memref == first_unmatched_memref)
|
||||
first_unmatched_memref = memref->next;
|
||||
|
||||
break;
|
||||
first_unmatched_memref++;
|
||||
if (first_unmatched_memref >= unmatched_memref_list->items + unmatched_memref_list->count) {
|
||||
unmatched_memref_list = unmatched_memref_list->next;
|
||||
if (!unmatched_memref_list)
|
||||
break;
|
||||
first_unmatched_memref = unmatched_memref_list->items;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rc_memref_list_t* memref_list = unmatched_memref_list;
|
||||
do {
|
||||
++memref;
|
||||
if (memref >= memref_list->items + memref_list->count) {
|
||||
memref_list = memref_list->next;
|
||||
if (!memref_list)
|
||||
break;
|
||||
|
||||
memref = memref->next;
|
||||
memref = memref_list->items;
|
||||
}
|
||||
|
||||
if (memref->address == address && memref->value.size == size) {
|
||||
memref->value.value = value;
|
||||
memref->value.changed = (flags & RC_MEMREF_FLAG_CHANGED_THIS_FRAME) ? 1 : 0;
|
||||
memref->value.prior = prior;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
}
|
||||
|
||||
--entries;
|
||||
}
|
||||
|
||||
rc_runtime_progress_update_modified_memrefs(progress);
|
||||
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
@@ -215,7 +306,10 @@ static int rc_runtime_progress_is_indirect_memref(rc_operand_t* oper)
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return oper->value.memref->value.is_indirect;
|
||||
if (oper->value.memref->value.memref_type != RC_MEMREF_TYPE_MODIFIED_MEMREF)
|
||||
return 0;
|
||||
|
||||
return ((const rc_modified_memref_t*)oper->value.memref)->modifier_type == RC_OPERATOR_INDIRECT_READ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,8 +411,8 @@ static uint32_t rc_runtime_progress_should_serialize_variable_condset(const rc_c
|
||||
{
|
||||
const rc_condition_t* condition;
|
||||
|
||||
/* predetermined presence of pause flag or indirect memrefs - must serialize */
|
||||
if (conditions->has_pause || conditions->has_indirect_memrefs)
|
||||
/* predetermined presence of pause flag - must serialize */
|
||||
if (conditions->has_pause)
|
||||
return RC_VAR_FLAG_HAS_COND_DATA;
|
||||
|
||||
/* if any conditions has required hits, must serialize */
|
||||
@@ -358,12 +452,15 @@ static int rc_runtime_progress_write_variable(rc_runtime_progress_t* progress, c
|
||||
|
||||
static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
const rc_value_t* variable;
|
||||
uint32_t count;
|
||||
const rc_value_t* value;
|
||||
int result;
|
||||
|
||||
for (variable = progress->runtime->variables; variable; variable = variable->next)
|
||||
++count;
|
||||
if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence)
|
||||
return RC_OK;
|
||||
|
||||
value = progress->runtime->richpresence->richpresence->values;
|
||||
count = rc_count_values(value);
|
||||
if (count == 0)
|
||||
return RC_OK;
|
||||
|
||||
@@ -374,14 +471,14 @@ static int rc_runtime_progress_write_variables(rc_runtime_progress_t* progress)
|
||||
rc_runtime_progress_start_chunk(progress, RC_RUNTIME_CHUNK_VARIABLES);
|
||||
rc_runtime_progress_write_uint(progress, count);
|
||||
|
||||
for (variable = progress->runtime->variables; variable; variable = variable->next) {
|
||||
uint32_t djb2 = rc_djb2(variable->name);
|
||||
for (; value; value = value->next) {
|
||||
const uint32_t djb2 = rc_djb2(value->name);
|
||||
if (progress->offset + 16 > progress->buffer_size)
|
||||
return RC_INSUFFICIENT_BUFFER;
|
||||
|
||||
rc_runtime_progress_write_uint(progress, djb2);
|
||||
|
||||
result = rc_runtime_progress_write_variable(progress, variable);
|
||||
result = rc_runtime_progress_write_variable(progress, value);
|
||||
if (result != RC_OK)
|
||||
return result;
|
||||
}
|
||||
@@ -418,19 +515,20 @@ static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress)
|
||||
};
|
||||
struct rc_pending_value_t local_pending_variables[32];
|
||||
struct rc_pending_value_t* pending_variables;
|
||||
rc_value_t* variable;
|
||||
rc_value_t* value;
|
||||
uint32_t count, serialized_count;
|
||||
int result;
|
||||
uint32_t i;
|
||||
int32_t i;
|
||||
|
||||
serialized_count = rc_runtime_progress_read_uint(progress);
|
||||
if (serialized_count == 0)
|
||||
return RC_OK;
|
||||
|
||||
count = 0;
|
||||
for (variable = progress->runtime->variables; variable; variable = variable->next)
|
||||
++count;
|
||||
if (!progress->runtime->richpresence || !progress->runtime->richpresence->richpresence)
|
||||
return RC_OK;
|
||||
|
||||
value = progress->runtime->richpresence->richpresence->values;
|
||||
count = rc_count_values(value);
|
||||
if (count == 0)
|
||||
return RC_OK;
|
||||
|
||||
@@ -443,22 +541,22 @@ static int rc_runtime_progress_read_variables(rc_runtime_progress_t* progress)
|
||||
return RC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
for (variable = progress->runtime->variables; variable; variable = variable->next) {
|
||||
pending_variables[count].variable = variable;
|
||||
pending_variables[count].djb2 = rc_djb2(variable->name);
|
||||
++count;
|
||||
i = (int32_t)count;
|
||||
for (; value; value = value->next) {
|
||||
--i;
|
||||
pending_variables[i].variable = value;
|
||||
pending_variables[i].djb2 = rc_djb2(value->name);
|
||||
}
|
||||
|
||||
result = RC_OK;
|
||||
for (; serialized_count > 0 && result == RC_OK; --serialized_count) {
|
||||
uint32_t djb2 = rc_runtime_progress_read_uint(progress);
|
||||
for (i = 0; i < count; ++i) {
|
||||
for (i = (int32_t)count - 1; i >= 0; --i) {
|
||||
if (pending_variables[i].djb2 == djb2) {
|
||||
variable = pending_variables[i].variable;
|
||||
result = rc_runtime_progress_read_variable(progress, variable);
|
||||
value = pending_variables[i].variable;
|
||||
result = rc_runtime_progress_read_variable(progress, value);
|
||||
if (result == RC_OK) {
|
||||
if (i < count - 1)
|
||||
if (i < (int32_t)count - 1)
|
||||
memcpy(&pending_variables[i], &pending_variables[count - 1], sizeof(struct rc_pending_value_t));
|
||||
count--;
|
||||
}
|
||||
@@ -742,7 +840,7 @@ static int rc_runtime_progress_read_rich_presence(rc_runtime_progress_t* progres
|
||||
return RC_OK;
|
||||
|
||||
if (!rc_runtime_progress_match_md5(progress, progress->runtime->richpresence->md5)) {
|
||||
rc_reset_richpresence(progress->runtime->richpresence->richpresence);
|
||||
rc_reset_richpresence_triggers(progress->runtime->richpresence->richpresence);
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
@@ -958,7 +1056,7 @@ int rc_runtime_deserialize_progress_sized(rc_runtime_t* runtime, const uint8_t*
|
||||
}
|
||||
|
||||
if (!seen_rich_presence && runtime->richpresence && runtime->richpresence->richpresence)
|
||||
rc_reset_richpresence(runtime->richpresence->richpresence);
|
||||
rc_reset_richpresence_triggers(runtime->richpresence->richpresence);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -16,21 +16,20 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars
|
||||
parse->measured_as_percent = 0;
|
||||
|
||||
if (*aux == 's' || *aux == 'S') {
|
||||
self->requirement = 0;
|
||||
self->requirement = NULL;
|
||||
}
|
||||
else {
|
||||
self->requirement = rc_parse_condset(&aux, parse, 0);
|
||||
self->requirement = rc_parse_condset(&aux, parse);
|
||||
|
||||
if (parse->offset < 0) {
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
self->requirement->next = 0;
|
||||
self->requirement->next = NULL;
|
||||
}
|
||||
|
||||
while (*aux == 's' || *aux == 'S') {
|
||||
aux++;
|
||||
*next = rc_parse_condset(&aux, parse, 0);
|
||||
*next = rc_parse_condset(&aux, parse);
|
||||
|
||||
if (parse->offset < 0) {
|
||||
return;
|
||||
@@ -39,7 +38,7 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars
|
||||
next = &(*next)->next;
|
||||
}
|
||||
|
||||
*next = 0;
|
||||
*next = NULL;
|
||||
*memaddr = aux;
|
||||
|
||||
self->measured_target = parse->measured_target;
|
||||
@@ -47,39 +46,46 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars
|
||||
self->measured_as_percent = parse->measured_as_percent;
|
||||
self->state = RC_TRIGGER_STATE_WAITING;
|
||||
self->has_hits = 0;
|
||||
self->has_required_hits = parse->has_required_hits;
|
||||
self->has_memrefs = 0;
|
||||
}
|
||||
|
||||
int rc_trigger_size(const char* memaddr) {
|
||||
rc_trigger_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_memref_t* memrefs;
|
||||
rc_init_parse_state(&parse, 0, 0, 0);
|
||||
rc_init_parse_state_memrefs(&parse, &memrefs);
|
||||
rc_trigger_with_memrefs_t* trigger;
|
||||
rc_preparse_state_t preparse;
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
|
||||
self = RC_ALLOC(rc_trigger_t, &parse);
|
||||
rc_parse_trigger_internal(self, &memaddr, &parse);
|
||||
trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse);
|
||||
rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(NULL, &preparse);
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return parse.offset;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) {
|
||||
rc_trigger_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_trigger_with_memrefs_t* trigger;
|
||||
rc_preparse_state_t preparse;
|
||||
const char* preparse_memaddr = memaddr;
|
||||
|
||||
if (!buffer || !memaddr)
|
||||
return NULL;
|
||||
|
||||
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
|
||||
/* first pass : determine how many memrefs are needed */
|
||||
rc_init_preparse_state(&preparse, L, funcs_ndx);
|
||||
trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse);
|
||||
rc_parse_trigger_internal(&trigger->trigger, &preparse_memaddr, &preparse.parse);
|
||||
|
||||
self = RC_ALLOC(rc_trigger_t, &parse);
|
||||
rc_init_parse_state_memrefs(&parse, &self->memrefs);
|
||||
/* allocate the trigger and memrefs */
|
||||
rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx);
|
||||
trigger = RC_ALLOC(rc_trigger_with_memrefs_t, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(&trigger->memrefs, &preparse);
|
||||
|
||||
rc_parse_trigger_internal(self, &memaddr, &parse);
|
||||
/* parse the trigger */
|
||||
rc_parse_trigger_internal(&trigger->trigger, &memaddr, &preparse.parse);
|
||||
trigger->trigger.has_memrefs = 1;
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return (parse.offset >= 0) ? self : NULL;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return (preparse.parse.offset >= 0) ? &trigger->trigger : NULL;
|
||||
}
|
||||
|
||||
int rc_trigger_state_active(int state)
|
||||
@@ -124,9 +130,27 @@ static void rc_reset_trigger_hitcounts(rc_trigger_t* self) {
|
||||
}
|
||||
}
|
||||
|
||||
static void rc_update_trigger_memrefs(rc_trigger_t* self, rc_peek_t peek, void* ud) {
|
||||
if (self->has_memrefs) {
|
||||
rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self;
|
||||
rc_update_memref_values(&trigger->memrefs, peek, ud);
|
||||
}
|
||||
}
|
||||
|
||||
rc_memrefs_t* rc_trigger_get_memrefs(rc_trigger_t* self) {
|
||||
if (self->has_memrefs) {
|
||||
rc_trigger_with_memrefs_t* trigger = (rc_trigger_with_memrefs_t*)self;
|
||||
return &trigger->memrefs;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
rc_eval_state_t eval_state;
|
||||
rc_condset_t* condset;
|
||||
rc_typed_value_t measured_value;
|
||||
int measured_from_hits = 0;
|
||||
int ret;
|
||||
char is_paused;
|
||||
char is_primed;
|
||||
@@ -143,7 +167,7 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State*
|
||||
|
||||
case RC_TRIGGER_STATE_INACTIVE:
|
||||
/* not yet active. update the memrefs so deltas are correct when it becomes active, then return INACTIVE */
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
rc_update_trigger_memrefs(self, peek, ud);
|
||||
return RC_TRIGGER_STATE_INACTIVE;
|
||||
|
||||
default:
|
||||
@@ -151,18 +175,29 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State*
|
||||
}
|
||||
|
||||
/* update the memory references */
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
rc_update_trigger_memrefs(self, peek, ud);
|
||||
|
||||
/* process the trigger */
|
||||
memset(&eval_state, 0, sizeof(eval_state));
|
||||
eval_state.peek = peek;
|
||||
eval_state.peek_userdata = ud;
|
||||
#ifndef RC_DISABLE_LUA
|
||||
eval_state.L = L;
|
||||
#else
|
||||
(void)L;
|
||||
#endif
|
||||
|
||||
measured_value.type = RC_VALUE_TYPE_NONE;
|
||||
|
||||
if (self->requirement != NULL) {
|
||||
ret = rc_test_condset(self->requirement, &eval_state);
|
||||
is_paused = self->requirement->is_paused;
|
||||
is_primed = eval_state.primed;
|
||||
is_paused = eval_state.is_paused;
|
||||
is_primed = eval_state.is_primed;
|
||||
|
||||
if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) {
|
||||
memcpy(&measured_value, &eval_state.measured_value, sizeof(measured_value));
|
||||
measured_from_hits = eval_state.measured_from_hits;
|
||||
}
|
||||
} else {
|
||||
ret = 1;
|
||||
is_paused = 0;
|
||||
@@ -177,8 +212,17 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State*
|
||||
|
||||
do {
|
||||
sub |= rc_test_condset(condset, &eval_state);
|
||||
sub_paused &= condset->is_paused;
|
||||
sub_primed |= eval_state.primed;
|
||||
sub_paused &= eval_state.is_paused;
|
||||
sub_primed |= eval_state.is_primed;
|
||||
|
||||
if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) {
|
||||
/* if no previous Measured value was captured, or the new one is greater, keep the new one */
|
||||
if (measured_value.type == RC_VALUE_TYPE_NONE ||
|
||||
rc_typed_value_compare(&eval_state.measured_value, &measured_value, RC_OPERATOR_GT)) {
|
||||
memcpy(&measured_value, &eval_state.measured_value, sizeof(measured_value));
|
||||
measured_from_hits = eval_state.measured_from_hits;
|
||||
}
|
||||
}
|
||||
|
||||
condset = condset->next;
|
||||
} while (condset);
|
||||
@@ -193,15 +237,15 @@ int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State*
|
||||
|
||||
/* if paused, the measured value may not be captured, keep the old value */
|
||||
if (!is_paused) {
|
||||
rc_typed_value_convert(&eval_state.measured_value, RC_VALUE_TYPE_UNSIGNED);
|
||||
self->measured_value = eval_state.measured_value.value.u32;
|
||||
rc_typed_value_convert(&measured_value, RC_VALUE_TYPE_UNSIGNED);
|
||||
self->measured_value = measured_value.value.u32;
|
||||
}
|
||||
|
||||
/* if any ResetIf condition was true, reset the hit counts */
|
||||
if (eval_state.was_reset) {
|
||||
/* if the measured value came from a hit count, reset it. do this before calling
|
||||
* rc_reset_trigger_hitcounts in case we need to call rc_condset_is_measured_from_hitcount */
|
||||
if (eval_state.measured_from_hits) {
|
||||
if (measured_from_hits) {
|
||||
self->measured_value = 0;
|
||||
}
|
||||
else if (is_paused && self->measured_value) {
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <float.h> /* FLT_EPSILON */
|
||||
#include <math.h> /* fmod */
|
||||
|
||||
|
||||
|
||||
int rc_is_valid_variable_character(char ch, int is_first) {
|
||||
if (is_first) {
|
||||
if (!isalpha((unsigned char)ch))
|
||||
@@ -27,7 +25,7 @@ static void rc_parse_cond_value(rc_value_t* self, const char** memaddr, rc_parse
|
||||
do
|
||||
{
|
||||
parse->measured_target = 0; /* passing is_value=1 should prevent any conflicts, but clear it out anyway */
|
||||
*next_clause = rc_parse_condset(memaddr, parse, 1);
|
||||
*next_clause = rc_parse_condset(memaddr, parse);
|
||||
if (parse->offset < 0) {
|
||||
return;
|
||||
}
|
||||
@@ -52,174 +50,238 @@ static void rc_parse_cond_value(rc_value_t* self, const char** memaddr, rc_parse
|
||||
(*next_clause)->next = 0;
|
||||
}
|
||||
|
||||
void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
static void rc_parse_legacy_value(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_condset_with_trailing_conditions_t* condset_with_conditions;
|
||||
rc_condition_t** next;
|
||||
rc_condset_t** next_clause;
|
||||
rc_condset_t* condset;
|
||||
rc_condition_t local_cond;
|
||||
rc_condition_t* cond;
|
||||
uint32_t num_measured_conditions;
|
||||
char buffer[64] = "A:";
|
||||
const char* buffer_ptr;
|
||||
char* ptr;
|
||||
char c;
|
||||
|
||||
/* convert legacy format into condset */
|
||||
self->conditions = RC_ALLOC(rc_condset_t, parse);
|
||||
memset(self->conditions, 0, sizeof(rc_condset_t));
|
||||
next_clause = &self->conditions;
|
||||
do {
|
||||
num_measured_conditions = 0;
|
||||
|
||||
next = &self->conditions->conditions;
|
||||
next_clause = &self->conditions->next;
|
||||
|
||||
for (;; ++(*memaddr)) {
|
||||
buffer[0] = 'A'; /* reset to AddSource */
|
||||
ptr = &buffer[2];
|
||||
|
||||
/* extract the next clause */
|
||||
for (;; ++(*memaddr)) {
|
||||
switch (**memaddr) {
|
||||
case '_': /* add next */
|
||||
case '$': /* maximum of */
|
||||
case '\0': /* end of string */
|
||||
case ':': /* end of leaderboard clause */
|
||||
case ')': /* end of rich presence macro */
|
||||
*ptr = '\0';
|
||||
break;
|
||||
|
||||
case '*':
|
||||
*ptr++ = '*';
|
||||
|
||||
buffer_ptr = *memaddr + 1;
|
||||
if (*buffer_ptr == '-') {
|
||||
buffer[0] = 'B'; /* change to SubSource */
|
||||
++(*memaddr); /* don't copy sign */
|
||||
++buffer_ptr; /* ignore sign when doing floating point check */
|
||||
}
|
||||
else if (*buffer_ptr == '+') {
|
||||
++buffer_ptr; /* ignore sign when doing floating point check */
|
||||
}
|
||||
|
||||
/* if it looks like a floating point number, add the 'f' prefix */
|
||||
while (isdigit((unsigned char)*buffer_ptr))
|
||||
++buffer_ptr;
|
||||
if (*buffer_ptr == '.')
|
||||
*ptr++ = 'f';
|
||||
continue;
|
||||
|
||||
default:
|
||||
*ptr++ = **memaddr;
|
||||
continue;
|
||||
/* count the number of joiners and add one to determine the number of clauses. */
|
||||
num_measured_conditions = 1;
|
||||
buffer_ptr = *memaddr;
|
||||
while ((c = *buffer_ptr++) && c != '$') {
|
||||
if (c == '_') {
|
||||
++num_measured_conditions;
|
||||
buffer[0] = 'A'; /* reset to AddSource */
|
||||
}
|
||||
else if (c == '*' && *buffer_ptr == '-') {
|
||||
/* multiplication by a negative number will convert to SubSource */
|
||||
++buffer_ptr;
|
||||
buffer[0] = 'B';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* process the clause */
|
||||
buffer_ptr = buffer;
|
||||
cond = rc_parse_condition(&buffer_ptr, parse, 0);
|
||||
/* if last condition is SubSource, we'll need to add a dummy condition for the Measured */
|
||||
if (buffer[0] == 'B')
|
||||
++num_measured_conditions;
|
||||
|
||||
condset_with_conditions = RC_ALLOC_WITH_TRAILING(rc_condset_with_trailing_conditions_t,
|
||||
rc_condition_t, conditions, num_measured_conditions, parse);
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
|
||||
if (*buffer_ptr) {
|
||||
/* whatever we copied as a single condition was not fully consumed */
|
||||
parse->offset = RC_INVALID_COMPARISON;
|
||||
return;
|
||||
}
|
||||
condset = (rc_condset_t*)condset_with_conditions;
|
||||
memset(condset, 0, sizeof(*condset));
|
||||
condset->num_measured_conditions = num_measured_conditions;
|
||||
cond = &condset_with_conditions->conditions[0];
|
||||
|
||||
next = &condset->conditions;
|
||||
|
||||
for (;; ++(*memaddr)) {
|
||||
buffer[0] = 'A'; /* reset to AddSource */
|
||||
ptr = &buffer[2];
|
||||
|
||||
/* extract the next clause */
|
||||
for (;; ++(*memaddr)) {
|
||||
switch (**memaddr) {
|
||||
case '_': /* add next */
|
||||
case '$': /* maximum of */
|
||||
case '\0': /* end of string */
|
||||
case ':': /* end of leaderboard clause */
|
||||
case ')': /* end of rich presence macro */
|
||||
*ptr = '\0';
|
||||
break;
|
||||
|
||||
case '*':
|
||||
*ptr++ = '*';
|
||||
|
||||
buffer_ptr = *memaddr + 1;
|
||||
if (*buffer_ptr == '-') {
|
||||
buffer[0] = 'B'; /* change to SubSource */
|
||||
++(*memaddr); /* don't copy sign */
|
||||
++buffer_ptr; /* ignore sign when doing floating point check */
|
||||
}
|
||||
else if (*buffer_ptr == '+') {
|
||||
++buffer_ptr; /* ignore sign when doing floating point check */
|
||||
}
|
||||
|
||||
/* if it looks like a floating point number, add the 'f' prefix */
|
||||
while (isdigit((unsigned char)*buffer_ptr))
|
||||
++buffer_ptr;
|
||||
if (*buffer_ptr == '.')
|
||||
*ptr++ = 'f';
|
||||
continue;
|
||||
|
||||
default:
|
||||
*ptr++ = **memaddr;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cond->oper) {
|
||||
case RC_OPERATOR_MULT:
|
||||
case RC_OPERATOR_DIV:
|
||||
case RC_OPERATOR_AND:
|
||||
case RC_OPERATOR_XOR:
|
||||
case RC_OPERATOR_MOD:
|
||||
case RC_OPERATOR_ADD:
|
||||
case RC_OPERATOR_SUB:
|
||||
case RC_OPERATOR_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* process the clause */
|
||||
if (!parse->buffer)
|
||||
cond = &local_cond;
|
||||
|
||||
buffer_ptr = buffer;
|
||||
rc_parse_condition_internal(cond, &buffer_ptr, parse);
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
|
||||
if (*buffer_ptr) {
|
||||
/* whatever we copied as a single condition was not fully consumed */
|
||||
parse->offset = RC_INVALID_COMPARISON;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rc_operator_is_modifying(cond->oper)) {
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*next = cond;
|
||||
|
||||
if (**memaddr == '_') {
|
||||
/* add next */
|
||||
*next = cond;
|
||||
next = &cond->next;
|
||||
continue;
|
||||
|
||||
if (**memaddr != '_') /* add next */
|
||||
break;
|
||||
|
||||
rc_condition_update_parse_state(cond, parse);
|
||||
++cond;
|
||||
}
|
||||
|
||||
/* end of clause */
|
||||
if (cond->type == RC_CONDITION_SUB_SOURCE) {
|
||||
/* cannot change SubSource to Measured. add a dummy condition */
|
||||
next = &cond->next;
|
||||
rc_condition_update_parse_state(cond, parse);
|
||||
if (parse->buffer)
|
||||
++cond;
|
||||
|
||||
buffer_ptr = "A:0";
|
||||
cond = rc_parse_condition(&buffer_ptr, parse, 0);
|
||||
rc_parse_condition_internal(cond, &buffer_ptr, parse);
|
||||
*next = cond;
|
||||
next = &cond->next;
|
||||
}
|
||||
|
||||
/* convert final AddSource condition to Measured */
|
||||
cond->type = RC_CONDITION_MEASURED;
|
||||
cond->next = 0;
|
||||
cond->next = NULL;
|
||||
rc_condition_update_parse_state(cond, parse);
|
||||
|
||||
/* finalize clause */
|
||||
*next_clause = condset;
|
||||
next_clause = &condset->next;
|
||||
|
||||
if (**memaddr != '$') {
|
||||
/* end of valid string */
|
||||
*next_clause = 0;
|
||||
*next_clause = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* max of ($), start a new clause */
|
||||
*next_clause = RC_ALLOC(rc_condset_t, parse);
|
||||
|
||||
if (parse->buffer) /* don't clear in sizing mode or pointer will break */
|
||||
memset(*next_clause, 0, sizeof(rc_condset_t));
|
||||
|
||||
next = &(*next_clause)->conditions;
|
||||
next_clause = &(*next_clause)->next;
|
||||
}
|
||||
++(*memaddr);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
const uint8_t was_value = parse->is_value;
|
||||
const rc_condition_t* condition;
|
||||
parse->is_value = 1;
|
||||
|
||||
/* if it starts with a condition flag (M: A: B: C:), parse the conditions */
|
||||
if ((*memaddr)[1] == ':') {
|
||||
if ((*memaddr)[1] == ':')
|
||||
rc_parse_cond_value(self, memaddr, parse);
|
||||
}
|
||||
else {
|
||||
else
|
||||
rc_parse_legacy_value(self, memaddr, parse);
|
||||
|
||||
if (parse->offset >= 0 && parse->buffer) {
|
||||
self->name = "(unnamed)";
|
||||
self->value.value = self->value.prior = 0;
|
||||
self->value.memref_type = RC_MEMREF_TYPE_VALUE;
|
||||
self->value.changed = 0;
|
||||
self->has_memrefs = 0;
|
||||
|
||||
for (condition = self->conditions->conditions; condition; condition = condition->next) {
|
||||
if (condition->type == RC_CONDITION_MEASURED) {
|
||||
if (rc_operand_is_float(&condition->operand1)) {
|
||||
self->value.size = RC_MEMSIZE_FLOAT;
|
||||
self->value.type = RC_VALUE_TYPE_FLOAT;
|
||||
}
|
||||
else {
|
||||
self->value.size = RC_MEMSIZE_32_BITS;
|
||||
self->value.type = RC_VALUE_TYPE_UNSIGNED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->name = "(unnamed)";
|
||||
self->value.value = self->value.prior = 0;
|
||||
self->value.changed = 0;
|
||||
self->next = 0;
|
||||
parse->is_value = was_value;
|
||||
}
|
||||
|
||||
int rc_value_size(const char* memaddr) {
|
||||
rc_value_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_memref_t* first_memref;
|
||||
rc_init_parse_state(&parse, 0, 0, 0);
|
||||
rc_init_parse_state_memrefs(&parse, &first_memref);
|
||||
rc_value_with_memrefs_t* value;
|
||||
rc_preparse_state_t preparse;
|
||||
rc_init_preparse_state(&preparse, NULL, 0);
|
||||
|
||||
self = RC_ALLOC(rc_value_t, &parse);
|
||||
rc_parse_value_internal(self, &memaddr, &parse);
|
||||
value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse);
|
||||
rc_parse_value_internal(&value->value, &memaddr, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(NULL, &preparse);
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return parse.offset;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return preparse.parse.offset;
|
||||
}
|
||||
|
||||
rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx) {
|
||||
rc_value_t* self;
|
||||
rc_parse_state_t parse;
|
||||
rc_value_with_memrefs_t* value;
|
||||
rc_preparse_state_t preparse;
|
||||
const char* preparse_memaddr = memaddr;
|
||||
|
||||
if (!buffer || !memaddr)
|
||||
return NULL;
|
||||
|
||||
rc_init_parse_state(&parse, buffer, L, funcs_ndx);
|
||||
rc_init_preparse_state(&preparse, L, funcs_ndx);
|
||||
value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse);
|
||||
rc_parse_value_internal(&value->value, &preparse_memaddr, &preparse.parse);
|
||||
|
||||
self = RC_ALLOC(rc_value_t, &parse);
|
||||
rc_init_parse_state_memrefs(&parse, &self->memrefs);
|
||||
rc_reset_parse_state(&preparse.parse, buffer, L, funcs_ndx);
|
||||
value = RC_ALLOC(rc_value_with_memrefs_t, &preparse.parse);
|
||||
rc_preparse_alloc_memrefs(&value->memrefs, &preparse);
|
||||
|
||||
rc_parse_value_internal(self, &memaddr, &parse);
|
||||
rc_parse_value_internal(&value->value, &memaddr, &preparse.parse);
|
||||
value->value.has_memrefs = 1;
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return (parse.offset >= 0) ? self : NULL;
|
||||
rc_destroy_preparse_state(&preparse);
|
||||
return (preparse.parse.offset >= 0) ? &value->value : NULL;
|
||||
}
|
||||
|
||||
static void rc_update_value_memrefs(rc_value_t* self, rc_peek_t peek, void* ud) {
|
||||
if (self->has_memrefs) {
|
||||
rc_value_with_memrefs_t* value = (rc_value_with_memrefs_t*)self;
|
||||
rc_update_memref_values(&value->memrefs, peek, ud);
|
||||
}
|
||||
}
|
||||
|
||||
int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
@@ -227,7 +289,7 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t
|
||||
rc_condset_t* condset;
|
||||
int valid = 0;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
rc_update_value_memrefs(self, peek, ud);
|
||||
|
||||
value->value.i32 = 0;
|
||||
value->type = RC_VALUE_TYPE_SIGNED;
|
||||
@@ -236,7 +298,11 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t
|
||||
memset(&eval_state, 0, sizeof(eval_state));
|
||||
eval_state.peek = peek;
|
||||
eval_state.peek_userdata = ud;
|
||||
#ifndef RC_DISABLE_LUA
|
||||
eval_state.L = L;
|
||||
#else
|
||||
(void)L;
|
||||
#endif
|
||||
|
||||
rc_test_condset(condset, &eval_state);
|
||||
|
||||
@@ -248,25 +314,21 @@ int rc_evaluate_value_typed(rc_value_t* self, rc_typed_value_t* value, rc_peek_t
|
||||
* NOTE: ResetIf only affects the current condset when used in values!
|
||||
*/
|
||||
rc_reset_condset(condset);
|
||||
|
||||
/* if the measured value came from a hit count, reset it too */
|
||||
if (eval_state.measured_from_hits) {
|
||||
eval_state.measured_value.value.u32 = 0;
|
||||
eval_state.measured_value.type = RC_VALUE_TYPE_UNSIGNED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
/* capture the first valid measurement */
|
||||
memcpy(value, &eval_state.measured_value, sizeof(*value));
|
||||
valid = 1;
|
||||
}
|
||||
else {
|
||||
/* multiple condsets are currently only used for the MAX_OF operation.
|
||||
* only keep the condset's value if it's higher than the current highest value.
|
||||
*/
|
||||
if (rc_typed_value_compare(&eval_state.measured_value, value, RC_OPERATOR_GT))
|
||||
if (eval_state.measured_value.type != RC_VALUE_TYPE_NONE) {
|
||||
if (!valid) {
|
||||
/* capture the first valid measurement, which may be negative */
|
||||
memcpy(value, &eval_state.measured_value, sizeof(*value));
|
||||
valid = 1;
|
||||
}
|
||||
else {
|
||||
/* multiple condsets are currently only used for the MAX_OF operation.
|
||||
* only keep the condset's value if it's higher than the current highest value.
|
||||
*/
|
||||
if (rc_typed_value_compare(&eval_state.measured_value, value, RC_OPERATOR_GT))
|
||||
memcpy(value, &eval_state.measured_value, sizeof(*value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,84 +379,81 @@ int rc_value_from_hits(rc_value_t* self)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rc_init_parse_state_variables(rc_parse_state_t* parse, rc_value_t** variables) {
|
||||
parse->variables = variables;
|
||||
*variables = 0;
|
||||
}
|
||||
|
||||
rc_value_t* rc_alloc_helper_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse)
|
||||
{
|
||||
rc_value_t** variables = parse->variables;
|
||||
rc_value_t* rc_alloc_variable(const char* memaddr, size_t memaddr_len, rc_parse_state_t* parse) {
|
||||
rc_value_t** value_ptr = parse->variables;
|
||||
rc_value_t* value;
|
||||
const char* name;
|
||||
uint32_t measured_target;
|
||||
|
||||
while ((value = *variables) != NULL) {
|
||||
if (!value_ptr)
|
||||
return NULL;
|
||||
|
||||
while (*value_ptr) {
|
||||
value = *value_ptr;
|
||||
if (strncmp(value->name, memaddr, memaddr_len) == 0 && value->name[memaddr_len] == 0)
|
||||
return value;
|
||||
|
||||
variables = &value->next;
|
||||
value_ptr = &value->next;
|
||||
}
|
||||
|
||||
value = RC_ALLOC_SCRATCH(rc_value_t, parse);
|
||||
memset(&value->value, 0, sizeof(value->value));
|
||||
value->value.size = RC_MEMSIZE_VARIABLE;
|
||||
value->memrefs = NULL;
|
||||
|
||||
/* capture name before calling parse as parse will update memaddr pointer */
|
||||
name = rc_alloc_str(parse, memaddr, memaddr_len);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
/* no match found, create a new entry */
|
||||
value = RC_ALLOC_SCRATCH(rc_value_t, parse);
|
||||
memset(value, 0, sizeof(value->value));
|
||||
value->value.size = RC_MEMSIZE_VARIABLE;
|
||||
value->next = NULL;
|
||||
|
||||
/* the helper variable likely has a Measured condition. capture the current measured_target so we can restore it
|
||||
* after generating the variable so the variable's Measured target doesn't conflict with the rest of the trigger. */
|
||||
measured_target = parse->measured_target;
|
||||
|
||||
/* disable variable resolution when defining a variable to prevent infinite recursion */
|
||||
variables = parse->variables;
|
||||
parse->variables = NULL;
|
||||
rc_parse_value_internal(value, &memaddr, parse);
|
||||
parse->variables = variables;
|
||||
|
||||
/* restore the measured target */
|
||||
parse->measured_target = measured_target;
|
||||
|
||||
/* store name after calling parse as parse will set name to (unnamed) */
|
||||
value->name = name;
|
||||
|
||||
/* append the new variable to the end of the list (have to re-evaluate in case any others were added) */
|
||||
while (*variables != NULL)
|
||||
variables = &(*variables)->next;
|
||||
*variables = value;
|
||||
|
||||
*value_ptr = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
void rc_update_variables(rc_value_t* variable, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
uint32_t rc_count_values(const rc_value_t* values) {
|
||||
uint32_t count = 0;
|
||||
while (values) {
|
||||
++count;
|
||||
values = values->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void rc_update_values(rc_value_t* values, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
rc_typed_value_t result;
|
||||
|
||||
while (variable) {
|
||||
if (rc_evaluate_value_typed(variable, &result, peek, ud, L)) {
|
||||
rc_value_t* value = values;
|
||||
for (; value; value = value->next) {
|
||||
if (rc_evaluate_value_typed(value, &result, peek, ud, L)) {
|
||||
/* store the raw bytes and type to be restored by rc_typed_value_from_memref_value */
|
||||
rc_update_memref_value(&variable->value, result.value.u32);
|
||||
variable->value.type = result.type;
|
||||
rc_update_memref_value(&value->value, result.value.u32);
|
||||
value->value.type = result.type;
|
||||
}
|
||||
|
||||
variable = variable->next;
|
||||
}
|
||||
}
|
||||
|
||||
void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref) {
|
||||
value->value.u32 = memref->value;
|
||||
void rc_reset_values(rc_value_t* values) {
|
||||
rc_value_t* value = values;
|
||||
|
||||
if (memref->size == RC_MEMSIZE_VARIABLE) {
|
||||
/* a variable can be any of the supported types, but the raw data was copied into u32 */
|
||||
value->type = memref->type;
|
||||
}
|
||||
else {
|
||||
/* not a variable, only u32 is supported */
|
||||
value->type = RC_VALUE_TYPE_UNSIGNED;
|
||||
}
|
||||
for (; value; value = value->next)
|
||||
rc_reset_value(value);
|
||||
}
|
||||
|
||||
void rc_typed_value_from_memref_value(rc_typed_value_t* value, const rc_memref_value_t* memref) {
|
||||
/* raw value is always u32, type can mark it as something else */
|
||||
value->value.u32 = memref->value;
|
||||
value->type = memref->type;
|
||||
}
|
||||
|
||||
void rc_typed_value_convert(rc_typed_value_t* value, char new_type) {
|
||||
@@ -483,8 +542,12 @@ void rc_typed_value_negate(rc_typed_value_t* value) {
|
||||
void rc_typed_value_add(rc_typed_value_t* value, const rc_typed_value_t* amount) {
|
||||
rc_typed_value_t converted;
|
||||
|
||||
if (amount->type != value->type && value->type != RC_VALUE_TYPE_NONE)
|
||||
amount = rc_typed_value_convert_into(&converted, amount, value->type);
|
||||
if (amount->type != value->type && value->type != RC_VALUE_TYPE_NONE) {
|
||||
if (amount->type == RC_VALUE_TYPE_FLOAT)
|
||||
rc_typed_value_convert(value, RC_VALUE_TYPE_FLOAT);
|
||||
else
|
||||
amount = rc_typed_value_convert_into(&converted, amount, value->type);
|
||||
}
|
||||
|
||||
switch (value->type)
|
||||
{
|
||||
@@ -651,56 +714,56 @@ void rc_typed_value_modulus(rc_typed_value_t* value, const rc_typed_value_t* amo
|
||||
|
||||
switch (amount->type)
|
||||
{
|
||||
case RC_VALUE_TYPE_UNSIGNED:
|
||||
if (amount->value.u32 == 0) { /* divide by zero */
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
case RC_VALUE_TYPE_UNSIGNED:
|
||||
if (amount->value.u32 == 0) { /* divide by zero */
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (value->type) {
|
||||
case RC_VALUE_TYPE_UNSIGNED: /* integer math */
|
||||
value->value.u32 %= amount->value.u32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_SIGNED: /* integer math */
|
||||
value->value.i32 %= (int)amount->value.u32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_FLOAT:
|
||||
amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT);
|
||||
switch (value->type) {
|
||||
case RC_VALUE_TYPE_UNSIGNED: /* integer math */
|
||||
value->value.u32 %= amount->value.u32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_SIGNED: /* integer math */
|
||||
value->value.i32 %= (int)amount->value.u32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_FLOAT:
|
||||
amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT);
|
||||
break;
|
||||
default:
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case RC_VALUE_TYPE_SIGNED:
|
||||
if (amount->value.i32 == 0) { /* divide by zero */
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (value->type) {
|
||||
case RC_VALUE_TYPE_SIGNED: /* integer math */
|
||||
value->value.i32 %= amount->value.i32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_UNSIGNED: /* integer math */
|
||||
value->value.u32 %= (unsigned)amount->value.i32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_FLOAT:
|
||||
amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT);
|
||||
break;
|
||||
default:
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case RC_VALUE_TYPE_FLOAT:
|
||||
break;
|
||||
|
||||
default:
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case RC_VALUE_TYPE_SIGNED:
|
||||
if (amount->value.i32 == 0) { /* divide by zero */
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (value->type) {
|
||||
case RC_VALUE_TYPE_SIGNED: /* integer math */
|
||||
value->value.i32 %= amount->value.i32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_UNSIGNED: /* integer math */
|
||||
value->value.u32 %= (unsigned)amount->value.i32;
|
||||
return;
|
||||
case RC_VALUE_TYPE_FLOAT:
|
||||
amount = rc_typed_value_convert_into(&converted, amount, RC_VALUE_TYPE_FLOAT);
|
||||
break;
|
||||
default:
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case RC_VALUE_TYPE_FLOAT:
|
||||
break;
|
||||
|
||||
default:
|
||||
value->type = RC_VALUE_TYPE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount->value.f32 == 0.0) { /* divide by zero */
|
||||
@@ -712,6 +775,44 @@ void rc_typed_value_modulus(rc_typed_value_t* value, const rc_typed_value_t* amo
|
||||
value->value.f32 = (float)fmod(value->value.f32, amount->value.f32);
|
||||
}
|
||||
|
||||
void rc_typed_value_combine(rc_typed_value_t* value, rc_typed_value_t* amount, uint8_t oper) {
|
||||
switch (oper) {
|
||||
case RC_OPERATOR_MULT:
|
||||
rc_typed_value_multiply(value, amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_DIV:
|
||||
rc_typed_value_divide(value, amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_AND:
|
||||
rc_typed_value_convert(value, RC_VALUE_TYPE_UNSIGNED);
|
||||
rc_typed_value_convert(amount, RC_VALUE_TYPE_UNSIGNED);
|
||||
value->value.u32 &= amount->value.u32;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_XOR:
|
||||
rc_typed_value_convert(value, RC_VALUE_TYPE_UNSIGNED);
|
||||
rc_typed_value_convert(amount, RC_VALUE_TYPE_UNSIGNED);
|
||||
value->value.u32 ^= amount->value.u32;
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_MOD:
|
||||
rc_typed_value_modulus(value, amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_ADD:
|
||||
rc_typed_value_add(value, amount);
|
||||
break;
|
||||
|
||||
case RC_OPERATOR_SUB:
|
||||
rc_typed_value_negate(amount);
|
||||
rc_typed_value_add(value, amount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int rc_typed_value_compare_floats(float f1, float f2, char oper) {
|
||||
if (f1 == f2) {
|
||||
/* exactly equal */
|
||||
|
||||
@@ -77,7 +77,7 @@ static void* filereader_open(const char* path)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(__STDC_WANT_SECURE_LIB__)
|
||||
#if defined(__STDC_SECURE_LIB__)
|
||||
/* have to use _SH_DENYNO because some cores lock the file while its loaded */
|
||||
fp = _wfsopen(wpath, L"rb", _SH_DENYNO);
|
||||
#else
|
||||
@@ -90,7 +90,7 @@ static void* filereader_open(const char* path)
|
||||
#else /* !WINVER >= 0x0500 */
|
||||
static void* filereader_open(const char* path)
|
||||
{
|
||||
#if defined(__STDC_WANT_SECURE_LIB__)
|
||||
#if defined(__STDC_SECURE_LIB__)
|
||||
#if defined(WINVER)
|
||||
/* have to use _SH_DENYNO because some cores lock the file while its loaded */
|
||||
return _fsopen(path, "rb", _SH_DENYNO);
|
||||
@@ -99,7 +99,7 @@ static void* filereader_open(const char* path)
|
||||
fopen_s(&fp, path, "rb");
|
||||
return fp;
|
||||
#endif
|
||||
#else /* !__STDC_WANT_SECURE_LIB__ */
|
||||
#else /* !__STDC_SECURE_LIB__ */
|
||||
return fopen(path, "rb");
|
||||
#endif
|
||||
}
|
||||
@@ -2513,6 +2513,7 @@ int rc_hash_generate_from_buffer(char hash[33], uint32_t console_id, const uint8
|
||||
case RC_CONSOLE_ATARI_LYNX:
|
||||
return rc_hash_lynx(hash, buffer, buffer_size);
|
||||
|
||||
case RC_CONSOLE_FAMICOM_DISK_SYSTEM:
|
||||
case RC_CONSOLE_NINTENDO:
|
||||
return rc_hash_nes(hash, buffer, buffer_size);
|
||||
|
||||
@@ -2818,6 +2819,7 @@ int rc_hash_generate_from_file(char hash[33], uint32_t console_id, const char* p
|
||||
case RC_CONSOLE_ARDUBOY:
|
||||
case RC_CONSOLE_ATARI_7800:
|
||||
case RC_CONSOLE_ATARI_LYNX:
|
||||
case RC_CONSOLE_FAMICOM_DISK_SYSTEM:
|
||||
case RC_CONSOLE_NINTENDO:
|
||||
case RC_CONSOLE_PC_ENGINE:
|
||||
case RC_CONSOLE_SUPER_CASSETTEVISION:
|
||||
@@ -3015,7 +3017,11 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (rc_path_compare_extension(ext, "a78"))
|
||||
if (rc_path_compare_extension(ext, "a26"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ATARI_2600;
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "a78"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_ATARI_7800;
|
||||
}
|
||||
@@ -3157,7 +3163,7 @@ void rc_hash_initialize_iterator(struct rc_hash_iterator* iterator, const char*
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "fds"))
|
||||
{
|
||||
iterator->consoles[0] = RC_CONSOLE_NINTENDO;
|
||||
iterator->consoles[0] = RC_CONSOLE_FAMICOM_DISK_SYSTEM;
|
||||
}
|
||||
else if (rc_path_compare_extension(ext, "fd"))
|
||||
{
|
||||
|
||||
162
duckstation.sln
162
duckstation.sln
@@ -67,6 +67,8 @@ Global
|
||||
DebugFast|x64 = DebugFast|x64
|
||||
DebugFast-Clang|ARM64 = DebugFast-Clang|ARM64
|
||||
DebugFast-Clang|x64 = DebugFast-Clang|x64
|
||||
Devel-Clang|ARM64 = Devel-Clang|ARM64
|
||||
Devel-Clang|x64 = Devel-Clang|x64
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release-Clang|ARM64 = Release-Clang|ARM64
|
||||
@@ -79,6 +81,44 @@ Global
|
||||
ReleaseLTCG-Clang-SSE2|x64 = ReleaseLTCG-Clang-SSE2|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.Build.0 = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.Build.0 = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.ActiveCfg = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.Build.0 = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.ActiveCfg = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.Build.0 = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.Build.0 = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.ActiveCfg = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.Build.0 = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.Build.0 = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.ActiveCfg = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.Build.0 = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -96,6 +136,10 @@ Global
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Release|x64.ActiveCfg = Release|x64
|
||||
{43540154-9E1E-409C-834F-B84BE5621388}.Release|x64.Build.0 = Release|x64
|
||||
@@ -130,6 +174,10 @@ Global
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Release|x64.ActiveCfg = Release|x64
|
||||
{BB08260F-6FBC-46AF-8924-090EE71360C6}.Release|x64.Build.0 = Release|x64
|
||||
@@ -164,6 +212,10 @@ Global
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Release|x64.ActiveCfg = Release|x64
|
||||
{EE054E08-3799-4A59-A422-18259C105FFD}.Release|x64.Build.0 = Release|x64
|
||||
@@ -198,6 +250,10 @@ Global
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Release|x64.ActiveCfg = Release|x64
|
||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.Release|x64.Build.0 = Release|x64
|
||||
@@ -232,6 +288,10 @@ Global
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Release|x64.ActiveCfg = Release|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Release|x64.Build.0 = Release|x64
|
||||
@@ -249,40 +309,6 @@ Global
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug|x64.Build.0 = Debug|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|ARM64.Build.0 = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.ActiveCfg = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang|x64.Build.0 = Debug-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.ActiveCfg = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Debug-Clang-SSE2|x64.Build.0 = Debug-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast|x64.Build.0 = DebugFast|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.ActiveCfg = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release|x64.Build.0 = Release|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|ARM64.Build.0 = Release-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.ActiveCfg = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.Release-Clang|x64.Build.0 = Release-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.ActiveCfg = ReleaseLTCG-Clang-SSE2|x64
|
||||
{28F14272-0EC4-41BB-849F-182ADB81AF70}.ReleaseLTCG-Clang-SSE2|x64.Build.0 = ReleaseLTCG-Clang-SSE2|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Debug|ARM64.ActiveCfg = Debug-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -300,6 +326,10 @@ Global
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Release|x64.ActiveCfg = Release|x64
|
||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1}.Release|x64.Build.0 = Release|x64
|
||||
@@ -334,6 +364,10 @@ Global
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BDA439C-6358-45FB-9994-2FF083BABE06}.Release|x64.Build.0 = Release|x64
|
||||
@@ -368,6 +402,10 @@ Global
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Release|x64.ActiveCfg = Release|x64
|
||||
{425D6C99-D1C8-43C2-B8AC-4D7B1D941017}.Release|x64.Build.0 = Release|x64
|
||||
@@ -402,6 +440,10 @@ Global
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Release|x64.ActiveCfg = Release|x64
|
||||
{DD944834-7899-4C1C-A4C1-064B5009D239}.Release|x64.Build.0 = Release|x64
|
||||
@@ -436,6 +478,10 @@ Global
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Release|x64.ActiveCfg = Release|x64
|
||||
{09553C96-9F39-49BF-8AE6-7ACBD07C410C}.Release|x64.Build.0 = Release|x64
|
||||
@@ -470,6 +516,10 @@ Global
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Release|x64.ActiveCfg = Release|x64
|
||||
{49953E1B-2EF7-46A4-B88B-1BF9E099093B}.Release|x64.Build.0 = Release|x64
|
||||
@@ -497,6 +547,8 @@ Global
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Release|x64.ActiveCfg = Release|x64
|
||||
{EA2B9C7A-B8CC-42F9-879B-191A98680C10}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
@@ -524,6 +576,10 @@ Global
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Release|x64.ActiveCfg = Release|x64
|
||||
{075CED82-6A20-46DF-94C7-9624AC9DDBEB}.Release|x64.Build.0 = Release|x64
|
||||
@@ -551,6 +607,8 @@ Global
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Release|x64.ActiveCfg = Release|x64
|
||||
{32EEAF44-57F8-4C6C-A6F0-DE5667123DD5}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
@@ -576,6 +634,9 @@ Global
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Release|x64.ActiveCfg = Release|x64
|
||||
{8906836E-F06E-46E8-B11A-74E5E8C7B8FB}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
@@ -605,6 +666,10 @@ Global
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Release|x64.ActiveCfg = Release|x64
|
||||
{4BA0A6D4-3AE1-42B2-9347-096FD023FF64}.Release|x64.Build.0 = Release|x64
|
||||
@@ -633,6 +698,8 @@ Global
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Release|x64.ActiveCfg = Release|x64
|
||||
{3029310E-4211-4C87-801A-72E130A648EF}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
@@ -661,6 +728,10 @@ Global
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Release|x64.ActiveCfg = Release|x64
|
||||
{E4357877-D459-45C7-B8F6-DCBB587BB528}.Release|x64.Build.0 = Release|x64
|
||||
@@ -695,6 +766,10 @@ Global
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BE398E6-B882-4248-9065-FECC8728E038}.Release|x64.Build.0 = Release|x64
|
||||
@@ -729,6 +804,10 @@ Global
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Release|x64.ActiveCfg = Release|x64
|
||||
{57F6206D-F264-4B07-BAF8-11B9BBE1F455}.Release|x64.Build.0 = Release|x64
|
||||
@@ -761,6 +840,9 @@ Global
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Release|x64.ActiveCfg = Release|x64
|
||||
{C51A346A-86B2-46DF-9BB3-D0AA7E5D8699}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
@@ -788,6 +870,10 @@ Global
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Release|x64.ActiveCfg = Release|x64
|
||||
{F351C4D8-594A-4850-B77B-3C1249812CCE}.Release|x64.Build.0 = Release|x64
|
||||
@@ -822,6 +908,10 @@ Global
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Release|x64.ActiveCfg = Release|x64
|
||||
{27B8D4BB-4F01-4432-BC14-9BF6CA458EEE}.Release|x64.Build.0 = Release|x64
|
||||
@@ -856,6 +946,10 @@ Global
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|ARM64.ActiveCfg = Devel-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|ARM64.Build.0 = Devel-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|x64.ActiveCfg = Devel-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Devel-Clang|x64.Build.0 = Devel-Clang|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Release|ARM64.ActiveCfg = Release-Clang|ARM64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Release|x64.ActiveCfg = Release|x64
|
||||
{1AD23A8A-4C20-434C-AE6B-0E07759EEB1E}.Release|x64.Build.0 = Release|x64
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
set(CMAKE_C_COMPILER /usr/bin/clang-16)
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/clang++-16)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
519
scripts/deps/build-dependencies-linux-cross.sh
Executable file
519
scripts/deps/build-dependencies-linux-cross.sh
Executable file
@@ -0,0 +1,519 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-FileCopyrightText: 2019-2024 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>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" == "-system-freetype" ]; then
|
||||
echo "Skipping building FreeType."
|
||||
SKIP_FREETYPE=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-harfbuzz" ]; then
|
||||
echo "Skipping building HarfBuzz."
|
||||
SKIP_HARFBUZZ=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-libjpeg" ]; then
|
||||
echo "Skipping building libjpeg."
|
||||
SKIP_LIBJPEG=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-libpng" ]; then
|
||||
echo "Skipping building libpng."
|
||||
SKIP_LIBPNG=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-libwebp" ]; then
|
||||
echo "Skipping building libwebp."
|
||||
SKIP_LIBWEBP=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-libzip" ]; then
|
||||
echo "Skipping building libzip."
|
||||
SKIP_LIBZIP=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-zstd" ]; then
|
||||
echo "Skipping building zstd."
|
||||
SKIP_ZSTD=true
|
||||
shift
|
||||
elif [ "$arg" == "-system-qt" ]; then
|
||||
echo "Skipping building Qt."
|
||||
SKIP_QT=true
|
||||
shift
|
||||
elif [ "$arg" == "-skip-download" ]; then
|
||||
echo "Not downloading sources."
|
||||
SKIP_DOWNLOAD=true
|
||||
shift
|
||||
elif [ "$arg" == "-skip-cleanup" ]; then
|
||||
echo "Not removing build directory."
|
||||
SKIP_CLEANUP=true
|
||||
shift
|
||||
elif [ "$arg" == "-only-download" ]; then
|
||||
echo "Only downloading sources."
|
||||
ONLY_DOWNLOAD=true
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
SCRIPTDIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
HOSTDIR="$1"
|
||||
if [ "${HOSTDIR:0:1}" != "/" ]; then
|
||||
HOSTDIR="$PWD/$HOSTDIR"
|
||||
fi
|
||||
CROSSARCH="$2"
|
||||
SYSROOTDIR="$3"
|
||||
if [ "${SYSROOTDIR:0:1}" != "/" ]; then
|
||||
SYSROOTDIR="$PWD/$SYSROOTDIR"
|
||||
fi
|
||||
INSTALLDIR="$4"
|
||||
if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
TOOLCHAINFILE="$INSTALLDIR/toolchain.cmake"
|
||||
CMAKE_COMMON=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_TOOLCHAIN_FILE="$TOOLCHAINFILE"
|
||||
-DCMAKE_PREFIX_PATH="$INSTALLDIR"
|
||||
-DCMAKE_INSTALL_PREFIX="$INSTALLDIR"
|
||||
)
|
||||
|
||||
# TODO: Pull all of this from the main file.
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.1.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
|
||||
ZSTD=1.5.6
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
LUNASVG=9af1ac7b90658a279b372add52d6f77a4ebb482c
|
||||
SHADERC=1c0d3d18819aa75ec74f1fbd9ff0461e1b69a4d6
|
||||
SOUNDTOUCH=463ade388f3a51da078dc9ed062bf28e4ba29da7
|
||||
SPIRV_CROSS=vulkan-sdk-1.3.290.0
|
||||
|
||||
mkdir -p "${INSTALLDIR}"
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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 "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" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/stenzek/shaderc/archive/$SHADERC.tar.gz" \
|
||||
-o "soundtouch-$SOUNDTOUCH.tar.gz" "https://github.com/stenzek/soundtouch/archive/$SOUNDTOUCH.tar.gz"
|
||||
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
|
||||
fe45c2af99f6102d2704277d392c1c83b55180a70bfd17fb888cc84a54b70573 soundtouch-$SOUNDTOUCH.tar.gz
|
||||
EOF
|
||||
|
||||
if [ "$SKIP_FREETYPE" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_HARFBUZZ" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBJPEG" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBPNG" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBWEBP" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBZIP" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZSTD" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
curl -C - -L -O "https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 zstd-$ZSTD.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_QT" != true ]; then
|
||||
if [ "$SKIP_DOWNLOAD" != true ]; 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" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-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
|
||||
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
|
||||
fi
|
||||
|
||||
# Only downloading sources?
|
||||
if [ "$ONLY_DOWNLOAD" == true ]; then
|
||||
exit 0
|
||||
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_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_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_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_FIND_ROOT_PATH "${INSTALLDIR};${SYSROOTDIR}")
|
||||
set(CMAKE_SYSROOT "${SYSROOTDIR}")
|
||||
|
||||
set(CMAKE_PKG_CONFIG_PC_PATH "${PKG_CONFIG_PATH}")
|
||||
set(CMAKE_PKG_CONFIG_SYSROOT_DIR "${PKG_CONFIG_SYSROOT_DIR}")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
EOF
|
||||
|
||||
# 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"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$INSTALLDIR" --build=x86_64-linux-gnu --host="${CROSSARCH}-linux-gnu" --with-pic --enable-shared --disable-static
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
|
||||
if [ "$SKIP_LIBPNG" != true ]; then
|
||||
echo "Building libpng..."
|
||||
rm -fr "libpng-$LIBPNG"
|
||||
tar xf "libpng-$LIBPNG.tar.xz"
|
||||
cd "libpng-$LIBPNG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ "$SKIP_LIBJPEG" != true ]; then
|
||||
echo "Building libjpeg..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake "${CMAKE_COMMON[@]}" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ "$SKIP_ZSTD" != true ]; then
|
||||
echo "Building Zstandard..."
|
||||
rm -fr "zstd-$ZSTD"
|
||||
tar xf "zstd-$ZSTD.tar.gz"
|
||||
cd "zstd-$ZSTD"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ "$SKIP_LIBWEBP" != true ]; then
|
||||
echo "Building WebP..."
|
||||
rm -fr "libwebp-$LIBWEBP"
|
||||
tar xf "libwebp-$LIBWEBP.tar.gz"
|
||||
cd "libwebp-$LIBWEBP"
|
||||
cmake "${CMAKE_COMMON[@]}" -B build -G Ninja \
|
||||
-DWEBP_BUILD_ANIM_UTILS=OFF -DWEBP_BUILD_CWEBP=OFF -DWEBP_BUILD_DWEBP=OFF -DWEBP_BUILD_GIF2WEBP=OFF -DWEBP_BUILD_IMG2WEBP=OFF \
|
||||
-DWEBP_BUILD_VWEBP=OFF -DWEBP_BUILD_WEBPINFO=OFF -DWEBP_BUILD_WEBPMUX=OFF -DWEBP_BUILD_EXTRAS=OFF -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ "$SKIP_LIBZIP" != true ]; then
|
||||
echo "Building libzip..."
|
||||
rm -fr "libzip-$LIBZIP"
|
||||
tar xf "libzip-$LIBZIP.tar.xz"
|
||||
cd "libzip-$LIBZIP"
|
||||
cmake "${CMAKE_COMMON[@]}" -B build -G Ninja \
|
||||
-DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_MBEDTLS=OFF -DENABLE_OPENSSL=OFF -DENABLE_WINDOWS_CRYPTO=OFF \
|
||||
-DENABLE_BZIP2=OFF -DENABLE_LZMA=OFF -DENABLE_ZSTD=ON -DBUILD_SHARED_LIBS=ON -DLIBZIP_DO_INSTALL=ON \
|
||||
-DBUILD_TOOLS=OFF -DBUILD_REGRESS=OFF -DBUILD_OSSFUZZ=OFF -DBUILD_EXAMPLES=OFF -DBUILD_DOC=OFF
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if [ "$SKIP_FREETYPE" != true ]; then
|
||||
if [ "$SKIP_HARFBUZZ" != true ]; then
|
||||
echo "Building FreeType without HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building HarfBuzz..."
|
||||
rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
fi
|
||||
|
||||
echo "Building FreeType with HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
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
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
if [ "$SKIP_QT" != true ]; then
|
||||
# Couple notes:
|
||||
# -fontconfig is needed otherwise Qt Widgets render only boxes.
|
||||
# -qt-doubleconversion avoids a dependency on libdouble-conversion.
|
||||
# ICU avoids pulling in a bunch of large libraries, and hopefully we can get away without it.
|
||||
# OpenGL is needed to render window decorations in Wayland, apparently.
|
||||
# dbus-runtime and linked off to avoid a relocation error (different to host.. probably should change that).
|
||||
echo "Building Qt Base..."
|
||||
rm -fr "qtbase-everywhere-src-$QT"
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
patch -p1 < "$SCRIPTDIR/qtbase-disable-pcre2-jit.patch"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure -prefix "$INSTALLDIR" -extprefix "$INSTALLDIR" -qt-host-path "$HOSTDIR" -release -dbus runtime -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -xcb -gtk -- -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAINFILE" -DFEATURE_cups=OFF -DFEATURE_dbus=ON -DFEATURE_dbus_linked=OFF -DFEATURE_icu=OFF -DFEATURE_sql=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt SVG..."
|
||||
rm -fr "qtsvg-everywhere-src-$QT"
|
||||
tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR"
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Image Formats..."
|
||||
rm -fr "qtimageformats-everywhere-src-$QT"
|
||||
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_system_webp=ON
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Wayland..."
|
||||
rm -fr "qtwayland-everywhere-src-$QT"
|
||||
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
|
||||
cd "qtwayland-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_wayland_server=OFF
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Installing Qt Tools..."
|
||||
rm -fr "qttools-everywhere-src-$QT"
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
|
||||
# Force disable clang scanning, it gets very confused.
|
||||
patch -u configure.cmake <<EOF
|
||||
--- configure.cmake
|
||||
+++ configure.cmake
|
||||
@@ -14,12 +14,12 @@
|
||||
# Presumably because 6.0 ClangConfig.cmake files are not good enough?
|
||||
# In any case explicitly request a minimum version of 8.x for now, otherwise
|
||||
# building with CMake will fail at compilation time.
|
||||
-qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
|
||||
+#qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
|
||||
# special case end
|
||||
|
||||
-if(TARGET WrapLibClang::WrapLibClang)
|
||||
- set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
|
||||
-endif()
|
||||
+#if(TARGET WrapLibClang::WrapLibClang)
|
||||
+# set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
|
||||
+#endif()
|
||||
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
|
||||
echo "Installing Qt Translations..."
|
||||
rm -fr "qttranslations-everywhere-src-$QT"
|
||||
tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- -DCMAKE_PREFIX_PATH="$INSTALLDIR"
|
||||
cmake --build . --parallel
|
||||
ninja install
|
||||
cd ../../
|
||||
fi
|
||||
|
||||
echo "Building shaderc..."
|
||||
rm -fr "shaderc-$SHADERC"
|
||||
tar xf "shaderc-$SHADERC.tar.gz"
|
||||
cd "shaderc-$SHADERC"
|
||||
cmake "${CMAKE_COMMON[@]}" -DSHADERC_SKIP_TESTS=ON -DSHADERC_SKIP_EXAMPLES=ON -DSHADERC_SKIP_COPYRIGHT_CHECK=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building SPIRV-Cross..."
|
||||
cd SPIRV-Cross
|
||||
rm -fr build
|
||||
cmake "${CMAKE_COMMON[@]}" -DSPIRV_CROSS_SHARED=ON -DSPIRV_CROSS_STATIC=OFF -DSPIRV_CROSS_CLI=OFF -DSPIRV_CROSS_ENABLE_TESTS=OFF -DSPIRV_CROSS_ENABLE_GLSL=ON -DSPIRV_CROSS_ENABLE_HLSL=OFF -DSPIRV_CROSS_ENABLE_MSL=OFF -DSPIRV_CROSS_ENABLE_CPP=OFF -DSPIRV_CROSS_ENABLE_REFLECT=OFF -DSPIRV_CROSS_ENABLE_C_API=ON -DSPIRV_CROSS_ENABLE_UTIL=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building cpuinfo..."
|
||||
rm -fr "cpuinfo-$CPUINFO"
|
||||
tar xf "cpuinfo-$CPUINFO.tar.gz"
|
||||
cd "cpuinfo-$CPUINFO"
|
||||
cmake "${CMAKE_COMMON[@]}" -DCPUINFO_LIBRARY_TYPE=shared -DCPUINFO_RUNTIME_TYPE=shared -DCPUINFO_LOG_LEVEL=error -DCPUINFO_LOG_TO_STDIO=ON -DCPUINFO_BUILD_TOOLS=OFF -DCPUINFO_BUILD_UNIT_TESTS=OFF -DCPUINFO_BUILD_MOCK_TESTS=OFF -DCPUINFO_BUILD_BENCHMARKS=OFF -DUSE_SYSTEM_LIBS=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building discord-rpc..."
|
||||
rm -fr "discord-rpc-$DISCORD_RPC"
|
||||
tar xf "discord-rpc-$DISCORD_RPC.tar.gz"
|
||||
cd "discord-rpc-$DISCORD_RPC"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building lunasvg..."
|
||||
rm -fr "lunasvg-$LUNASVG"
|
||||
tar xf "lunasvg-$LUNASVG.tar.gz"
|
||||
cd "lunasvg-$LUNASVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DLUNASVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building soundtouch..."
|
||||
rm -fr "soundtouch-$SOUNDTOUCH"
|
||||
tar xf "soundtouch-$SOUNDTOUCH.tar.gz"
|
||||
cd "soundtouch-$SOUNDTOUCH"
|
||||
cmake "${CMAKE_COMMON[@]}" -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
if [ "$SKIP_CLEANUP" != true ]; then
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -fr deps-build
|
||||
fi
|
||||
@@ -6,7 +6,7 @@
|
||||
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] <output directory>"
|
||||
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>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -51,6 +51,10 @@ for arg in "$@"; do
|
||||
echo "Not removing build directory."
|
||||
SKIP_CLEANUP=true
|
||||
shift
|
||||
elif [ "$arg" == "-only-download" ]; then
|
||||
echo "Only downloading sources."
|
||||
ONLY_DOWNLOAD=true
|
||||
shift
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -62,14 +66,14 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
HARFBUZZ=10.1.0
|
||||
LIBBACKTRACE=86885d14049fab06ef8a33aac51664230ca09200
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBPNG=1.6.44
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.1
|
||||
SDL2=2.30.9
|
||||
QT=6.8.0
|
||||
LIBZIP=1.11.2
|
||||
SDL2=2.30.11
|
||||
QT=6.8.1
|
||||
ZSTD=1.5.6
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
@@ -95,7 +99,7 @@ fi
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
baf8aebd22002b762d803ba0e1e389b6b4415159334e9d34bba1a938f6de8ce6 $LIBBACKTRACE.tar.gz
|
||||
24b574f71c87a763f50704bbb630cbe38298d544a1f890f099a4696b1d6beba4 SDL2-$SDL2.tar.gz
|
||||
8b8d4aef2038533da814965220f88f77d60dfa0f32685f80ead65e501337da7f SDL2-$SDL2.tar.gz
|
||||
e1351218d270db49c3dddcba04fb2153b09731ea3fa6830e423f5952f44585be cpuinfo-$CPUINFO.tar.gz
|
||||
3eea5ccce6670c126282f1ba4d32c19d486db49a1a5cbfb8d6f48774784d310c discord-rpc-$DISCORD_RPC.tar.gz
|
||||
3998b024b0d442614a9ee270e76e018bb37a17b8c6941212171731123cbbcac7 lunasvg-$LUNASVG.tar.gz
|
||||
@@ -116,7 +120,7 @@ if [ "$SKIP_HARFBUZZ" != true ]; then
|
||||
curl -C - -L -o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_LIBJPEG" != true ]; then
|
||||
@@ -148,7 +152,7 @@ if [ "$SKIP_LIBZIP" != true ]; then
|
||||
curl -C - -L -O "https://github.com/nih-at/libzip/releases/download/v$LIBZIP/libzip-$LIBZIP.tar.xz"
|
||||
fi
|
||||
cat >> SHASUMS <<EOF
|
||||
721e0e4e851073b508c243fd75eda04e4c5006158a900441de10ce274cc3b633 libzip-$LIBZIP.tar.xz
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
EOF
|
||||
fi
|
||||
if [ "$SKIP_ZSTD" != true ]; then
|
||||
@@ -170,12 +174,12 @@ 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
|
||||
1bad481710aa27f872de6c9f72651f89a6107f0077003d0ebfcc9fd15cba3c75 qtbase-everywhere-src-$QT.tar.xz
|
||||
595bf8557b91e1f8ebc726f1e09868a3c7e610ff5045068f2d4ea2428c49a5d4 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
cf7a593d5e520f8177240610d9e55d5b75b0887fe5f385554ff64377f1646199 qtsvg-everywhere-src-$QT.tar.xz
|
||||
403115d8268503c6cc6e43310c8ae28eb9e605072a5d04e4a2de8b6af39981f7 qttools-everywhere-src-$QT.tar.xz
|
||||
84bf2b67c243cd0c50a08acd7bfa9df2b1965028511815c1b6b65a0687437cb6 qttranslations-everywhere-src-$QT.tar.xz
|
||||
175758591638ebf1c6fbb66ac11c7fa0eb8d4ed52e9243cc59075d06a6a2060a qtwayland-everywhere-src-$QT.tar.xz
|
||||
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
|
||||
EOF
|
||||
fi
|
||||
|
||||
@@ -188,6 +192,11 @@ if [ "$SKIP_DOWNLOAD" != true ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Only downloading sources?
|
||||
if [ "$ONLY_DOWNLOAD" == true ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
tar xf "$LIBBACKTRACE.tar.gz"
|
||||
|
||||
@@ -37,16 +37,16 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=10.0.1
|
||||
SDL2=2.30.9
|
||||
HARFBUZZ=10.1.0
|
||||
SDL2=2.30.11
|
||||
ZSTD=1.5.6
|
||||
LIBPNG=1.6.44
|
||||
LIBJPEGTURBO=3.0.4
|
||||
LIBWEBP=1.4.0
|
||||
LIBZIP=1.11.1
|
||||
FFMPEG=7.0.2
|
||||
LIBZIP=1.11.2
|
||||
FFMPEG=7.1
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.8.0
|
||||
QT=6.8.1
|
||||
|
||||
CPUINFO=7524ad504fdcfcf75a18a133da6abd75c5d48053
|
||||
DISCORD_RPC=144f3a3f1209994d8d9e8a87964a989cb9911c1e
|
||||
@@ -73,22 +73,28 @@ CMAKE_ARCH_X64=-DCMAKE_OSX_ARCHITECTURES="x86_64"
|
||||
CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
|
||||
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
|
||||
# SBOM generation appears to be broken on MacOS, and I can't be arsed to debug it.
|
||||
CMAKE_COMMON_QT=(
|
||||
-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
-DQT_GENERATE_SBOM=OFF
|
||||
)
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
e7358ea86fe10fb9261931af6f010d4358dac64f7074420ca9bc94aae2bdd542 harfbuzz-$HARFBUZZ.tar.gz
|
||||
c758fdce8587641b00403ee0df2cd5d30cbea7803d43c65fddd76224f7b49b88 harfbuzz-$HARFBUZZ.tar.gz
|
||||
60c4da1d5b7f0aa8d158da48e8f8afa9773c1c8baa5d21974df61f1886b8ce8e libpng-$LIBPNG.tar.xz
|
||||
99130559e7d62e8d695f2c0eaeef912c5828d5b84a0537dcb24c9678c9d5b76b libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 libwebp-$LIBWEBP.tar.gz
|
||||
721e0e4e851073b508c243fd75eda04e4c5006158a900441de10ce274cc3b633 libzip-$LIBZIP.tar.xz
|
||||
24b574f71c87a763f50704bbb630cbe38298d544a1f890f099a4696b1d6beba4 SDL2-$SDL2.tar.gz
|
||||
5d471308cef4c4752bbcf973d9cd37ba4cb53739116c30349d4764ba1410dfc1 libzip-$LIBZIP.tar.xz
|
||||
8b8d4aef2038533da814965220f88f77d60dfa0f32685f80ead65e501337da7f SDL2-$SDL2.tar.gz
|
||||
8c29e06cf42aacc1eafc4077ae2ec6c6fcb96a626157e0593d5e82a34fd403c1 zstd-$ZSTD.tar.gz
|
||||
8646515b638a3ad303e23af6a3587734447cb8fc0a0c064ecdb8e95c4fd8b389 ffmpeg-$FFMPEG.tar.xz
|
||||
40973d44970dbc83ef302b0609f2e74982be2d85916dd2ee7472d30678a7abe6 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
1bad481710aa27f872de6c9f72651f89a6107f0077003d0ebfcc9fd15cba3c75 qtbase-everywhere-src-$QT.tar.xz
|
||||
595bf8557b91e1f8ebc726f1e09868a3c7e610ff5045068f2d4ea2428c49a5d4 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
cf7a593d5e520f8177240610d9e55d5b75b0887fe5f385554ff64377f1646199 qtsvg-everywhere-src-$QT.tar.xz
|
||||
403115d8268503c6cc6e43310c8ae28eb9e605072a5d04e4a2de8b6af39981f7 qttools-everywhere-src-$QT.tar.xz
|
||||
84bf2b67c243cd0c50a08acd7bfa9df2b1965028511815c1b6b65a0687437cb6 qttranslations-everywhere-src-$QT.tar.xz
|
||||
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
|
||||
3eea5ccce6670c126282f1ba4d32c19d486db49a1a5cbfb8d6f48774784d310c discord-rpc-$DISCORD_RPC.tar.gz
|
||||
3998b024b0d442614a9ee270e76e018bb37a17b8c6941212171731123cbbcac7 lunasvg-$LUNASVG.tar.gz
|
||||
@@ -301,7 +307,7 @@ patch -u src/tools/macdeployqt/shared/shared.cpp <<EOF
|
||||
// Platforminputcontext plugins if QtGui is in use
|
||||
EOF
|
||||
|
||||
cmake -B build "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
cmake -B build "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}" -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF -DFEATURE_system_png=ON -DFEATURE_system_jpeg=ON -DFEATURE_system_zlib=ON -DFEATURE_system_freetype=ON -DFEATURE_system_harfbuzz=ON
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
@@ -312,7 +318,7 @@ tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}"
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -323,7 +329,7 @@ tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_system_webp=ON
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}" -DFEATURE_system_webp=ON
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -334,7 +340,7 @@ tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_linguist=ON -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}" -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=ON -DFEATURE_kmap2qmap=OFF -DFEATURE_linguist=ON -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
@@ -345,7 +351,7 @@ tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL"
|
||||
"$INSTALLDIR/bin/qt-configure-module" .. -- "${CMAKE_COMMON[@]}" "${CMAKE_COMMON_QT[@]}"
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ../..
|
||||
|
||||
@@ -46,14 +46,14 @@ echo INSTALLDIR=%INSTALLDIR%
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set HARFBUZZ=10.1.0
|
||||
set LIBJPEGTURBO=3.0.4
|
||||
set LIBPNG=1644
|
||||
set QT=6.8.0
|
||||
set QT=6.8.1
|
||||
set QTMINOR=6.8
|
||||
set SDL2=2.30.9
|
||||
set SDL2=2.30.11
|
||||
set WEBP=1.4.0
|
||||
set LIBZIP=1.11.1
|
||||
set LIBZIP=1.11.2
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.6
|
||||
@@ -68,20 +68,20 @@ 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" 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || 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" ec855bcd815b4b63d0c958c42c2923311c656227d6e0c1ae1e721406d346444b || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c3b41915341d853b6374cf93f1fcced2c8e4be9360f29c656960e1d0d15046a3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 809081a7bdf7e48262fbe9437e4e756df6ad2649433e803c4040026e650d7c91 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 89f1ef4595f68c3d34c63a7c1c4ce475e701e103f0473f3fd0718a2e5234de6e || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 3f813f49d6d28c532dc4b104084f60ff382337f184698fcd6e70ab9efad977c1 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 91c33d9946279c9c613b02e52a33df610cc01d13ea6e321b4c4d8ee708b9a03e || 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" c0e6fa52a62ba11efd30262290dc6970947aef32e0cc294ee50e9005ceac092a || 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 "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 675f144b11f8ab2424b64bed8ccdca5d3f35b9326046fa7a883925dd180f0651 || 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 "discord-rpc-%DISCORD_RPC%.zip" "https://github.com/stenzek/discord-rpc/archive/%DISCORD_RPC%.zip" 61e185e75d37b360c314125bcdf4697192d15e2d5209db3306ed6cd736d508b3 || goto error
|
||||
|
||||
@@ -44,14 +44,14 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set FREETYPE=2.13.3
|
||||
set HARFBUZZ=10.0.1
|
||||
set HARFBUZZ=10.1.0
|
||||
set LIBJPEGTURBO=3.0.4
|
||||
set LIBPNG=1644
|
||||
set QT=6.8.0
|
||||
set QT=6.8.1
|
||||
set QTMINOR=6.8
|
||||
set SDL2=2.30.9
|
||||
set SDL2=2.30.11
|
||||
set WEBP=1.4.0
|
||||
set LIBZIP=1.11.1
|
||||
set LIBZIP=1.11.2
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.6
|
||||
@@ -66,20 +66,20 @@ 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" 8adf9f5a4b6022aa2744f45c89ce347df46fea8403e99f01d650b11c417d0aa8 || 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" ec855bcd815b4b63d0c958c42c2923311c656227d6e0c1ae1e721406d346444b || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" c3b41915341d853b6374cf93f1fcced2c8e4be9360f29c656960e1d0d15046a3 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 809081a7bdf7e48262fbe9437e4e756df6ad2649433e803c4040026e650d7c91 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 89f1ef4595f68c3d34c63a7c1c4ce475e701e103f0473f3fd0718a2e5234de6e || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 3f813f49d6d28c532dc4b104084f60ff382337f184698fcd6e70ab9efad977c1 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 91c33d9946279c9c613b02e52a33df610cc01d13ea6e321b4c4d8ee708b9a03e || 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" c0e6fa52a62ba11efd30262290dc6970947aef32e0cc294ee50e9005ceac092a || 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 "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 675f144b11f8ab2424b64bed8ccdca5d3f35b9326046fa7a883925dd180f0651 || 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 "discord-rpc-%DISCORD_RPC%.zip" "https://github.com/stenzek/discord-rpc/archive/%DISCORD_RPC%.zip" 61e185e75d37b360c314125bcdf4697192d15e2d5209db3306ed6cd736d508b3 || goto error
|
||||
|
||||
13
scripts/deps/sdl2-disable-isystem.patch
Normal file
13
scripts/deps/sdl2-disable-isystem.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
--- 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")
|
||||
15
scripts/generate_release_commit_list.sh
Executable file
15
scripts/generate_release_commit_list.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Syntax: $0 <commit range, start..end>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS="
|
||||
"
|
||||
|
||||
printf "## Commits\n"
|
||||
for i in $(git log --oneline --reverse "$1"); do
|
||||
printf -- "- %s\n" "$i"
|
||||
done
|
||||
|
||||
21
scripts/packaging/appimage/apprun-cross.sh
Executable file
21
scripts/packaging/appimage/apprun-cross.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
# autogenerated by linuxdeploy
|
||||
|
||||
# make sure errors in sourced scripts will cause this script to stop
|
||||
set -e
|
||||
|
||||
this_dir="$(readlink -f "$(dirname "$0")")"
|
||||
|
||||
# generated by linuxdeploy-plugin-qt
|
||||
|
||||
# try to make Qt apps more "native looking" on Gtk-based desktops, if possible
|
||||
# see https://github.com/AppImage/AppImageKit/issues/977#issue-462374883
|
||||
case "${XDG_CURRENT_DESKTOP}" in
|
||||
*GNOME*|*gnome*|*XFCE*)
|
||||
export QT_QPA_PLATFORMTHEME=gtk3
|
||||
;;
|
||||
esac
|
||||
|
||||
exec "$this_dir"/AppRun.wrapped "$@"
|
||||
|
||||
29
scripts/packaging/appimage/inject-libc-apprun.sh
Executable file
29
scripts/packaging/appimage/inject-libc-apprun.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
REQUIRED_GLIBC_VERSION="__REQ_GLIBC_VERSION__"
|
||||
|
||||
this_dir="$(readlink -f "$(dirname "$0")")"
|
||||
|
||||
APPBIN="${this_dir}/usr/bin/__APPNAME__"
|
||||
RUNTIME_DIR="${this_dir}/libc-runtime"
|
||||
LOADER_BIN="${this_dir}/usr/bin/ld-linux"
|
||||
|
||||
GLIBC_VERSION=$(ldd --version | head -1 | sed -e 's/.* \([0-9.]\)/\1/')
|
||||
|
||||
echo "Detected glibc version ${GLIBC_VERSION}."
|
||||
|
||||
if [[ -z "${GLIBC_VERSION}" || ! "${GLIBC_VERSION}" < "${REQUIRED_GLIBC_VERSION}" ]]; then
|
||||
echo "Using system libc/libstdc++."
|
||||
exec "${APPBIN}" "$@"
|
||||
fi
|
||||
|
||||
|
||||
echo "Using bundled libc/libstdc++ from ${RUNTIME_DIR}."
|
||||
if [ -z "$LD_LIBRARY_PATH" ]; then
|
||||
export LD_LIBRARY_PATH="${RUNTIME_DIR}"
|
||||
else
|
||||
export LD_LIBRARY_PATH="${RUNTIME_DIR}:${LD_LIBRARY_PATH}"
|
||||
fi
|
||||
|
||||
exec "${LOADER_BIN}" "${APPBIN}" "$@"
|
||||
|
||||
81
scripts/packaging/appimage/inject-libc.sh
Executable file
81
scripts/packaging/appimage/inject-libc.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
function retry_command {
|
||||
# Package servers tend to be unreliable at times..
|
||||
# Retry a bunch of times.
|
||||
local RETRIES=10
|
||||
|
||||
for i in $(seq 1 "$RETRIES"); do
|
||||
"$@" && break
|
||||
if [ "$i" == "$RETRIES" ]; then
|
||||
echo "Command \"$@\" failed after ${RETRIES} retries."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
this_dir="$(readlink -f "$(dirname "$0")")"
|
||||
|
||||
if [ "$#" -ne 5 ]; 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"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
APPDIR=$1
|
||||
DEBARCH=$2
|
||||
TRIPLE=$3
|
||||
MIRROR=$4
|
||||
APPNAME=$5
|
||||
|
||||
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
|
||||
|
||||
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" .
|
||||
|
||||
# Copy everything into AppDir
|
||||
RUNTIME="${APPDIR}/libc-runtime"
|
||||
mkdir -p "${RUNTIME}"
|
||||
|
||||
# libc.so.6 and friends
|
||||
cd "lib/${TRIPLE}"
|
||||
cp -v * "${RUNTIME}"
|
||||
cd ../../
|
||||
|
||||
# libstdc++
|
||||
cd "usr/lib/${TRIPLE}"
|
||||
cp -v * "${RUNTIME}" || true
|
||||
cd ../../..
|
||||
|
||||
# done with temps now
|
||||
cd ..
|
||||
rm -fr temp
|
||||
|
||||
# Not risking mixing resolvers...
|
||||
cd "${RUNTIME}"
|
||||
rm -vf libnss_*
|
||||
|
||||
# Move ld-linux.so.2 into the binary directory so we can preserve arg0's directory
|
||||
mv -v "ld-linux-"*.so.* "${APPDIR}/usr/bin/ld-linux"
|
||||
|
||||
# Set up the replacement apprun script
|
||||
cd "${APPDIR}"
|
||||
rm -f AppRun.wrapped
|
||||
cp "${this_dir}/inject-libc-apprun.sh" AppRun.wrapped
|
||||
sed -i -e "s/__APPNAME__/${APPNAME}/" AppRun.wrapped
|
||||
sed -i -e "s/__REQ_GLIBC_VERSION__/${GLIBC_VERSION}/" AppRun.wrapped
|
||||
|
||||
echo Done.
|
||||
|
||||
@@ -127,8 +127,8 @@ DEPLOY_PLATFORM_THEMES="1" \
|
||||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/duckstation-qt" ${EXTRA_LIBS_ARGS[@]} \
|
||||
--desktop-file="$ROOTDIR/scripts/org.duckstation.DuckStation.desktop" \
|
||||
--icon-file="$ROOTDIR/scripts/org.duckstation.DuckStation.png" \
|
||||
--desktop-file="$ROOTDIR/scripts/packaging/org.duckstation.DuckStation.desktop" \
|
||||
--icon-file="$ROOTDIR/scripts/packaging/org.duckstation.DuckStation.png" \
|
||||
|
||||
echo "Copying resources into AppDir..."
|
||||
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
|
||||
334
scripts/packaging/appimage/make-cross-appimage.sh
Executable file
334
scripts/packaging/appimage/make-cross-appimage.sh
Executable file
@@ -0,0 +1,334 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
function retry_command {
|
||||
# Package servers tend to be unreliable at times..
|
||||
# Retry a bunch of times.
|
||||
local RETRIES=10
|
||||
|
||||
for i in $(seq 1 "$RETRIES"); do
|
||||
"$@" && break
|
||||
if [ "$i" == "$RETRIES" ]; then
|
||||
echo "Command \"$@\" failed after ${RETRIES} retries."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
if [ "$1" == "-inject-libc" ]; then
|
||||
echo "Injecting libc/libstdc++"
|
||||
INJECT_LIBC=true
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
echo "Syntax: $0 [-inject-libc] <target arch> <path to build directory> <deps prefix> <chroot dir> <output name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ARCH=$1
|
||||
BUILDDIR=$2
|
||||
DEPSDIR=$3
|
||||
CHROOTDIR=$4
|
||||
NAME=$5
|
||||
|
||||
BINARY=duckstation-qt
|
||||
APPDIRNAME=DuckStation.AppDir
|
||||
STRIP=llvm-strip
|
||||
TRIPLE="${ARCH}-linux-gnu"
|
||||
|
||||
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=(
|
||||
"libbacktrace.so.0"
|
||||
"libfreetype.so.6"
|
||||
"libharfbuzz.so"
|
||||
"libjpeg.so.62"
|
||||
"libpng16.so.16"
|
||||
"libSDL2-2.0.so.0"
|
||||
"libsharpyuv.so.0"
|
||||
"libwebpdemux.so.2"
|
||||
"libwebpmux.so.3"
|
||||
"libwebp.so.7"
|
||||
"libzip.so.5"
|
||||
"libzstd.so.1"
|
||||
|
||||
"libcpuinfo.so"
|
||||
"libdiscord-rpc.so"
|
||||
"liblunasvg.so"
|
||||
"libshaderc_ds.so"
|
||||
"libsoundtouch.so.2"
|
||||
"libspirv-cross-c-shared.so.0"
|
||||
|
||||
#"libavcodec.so.61"
|
||||
#"libavformat.so.61"
|
||||
#"libavutil.so.59"
|
||||
#"libswscale.so.8"
|
||||
#"libswresample.so.5"
|
||||
#"libva-drm.so.2"
|
||||
#"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"
|
||||
)
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
set -e
|
||||
IFS="
|
||||
"
|
||||
|
||||
APPIMAGETOOL=./appimagetool-x86_64
|
||||
APPIMAGERUNTIME=./runtime-${ARCH}
|
||||
PATCHELF=patchelf
|
||||
|
||||
if [ ! -f "$APPIMAGETOOL" ]; then
|
||||
retry_command wget -O "$APPIMAGETOOL" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x "$APPIMAGETOOL"
|
||||
fi
|
||||
|
||||
if [ ! -f "$APPIMAGERUNTIME" ]; then
|
||||
retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${ARCH}
|
||||
fi
|
||||
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
rm -fr "$OUTDIR"
|
||||
mkdir "$OUTDIR"
|
||||
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"
|
||||
|
||||
# Libraries we pull in from the system.
|
||||
echo "Copying system libraries..."
|
||||
for lib in "${SYSLIBS[@]}"; do
|
||||
blib=$(basename "$lib")
|
||||
echo "$CHROOTDIR/lib/$TRIPLE/$lib"
|
||||
if [ -f "$CHROOTDIR/lib/$TRIPLE/$lib" ]; then
|
||||
cp "$CHROOTDIR/lib/$TRIPLE/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOTDIR/usr/lib/$TRIPLE/$lib" ]; then
|
||||
cp "$CHROOTDIR/usr/lib/$TRIPLE/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOTDIR/lib/$lib" ]; then
|
||||
cp "$CHROOTDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOTDIR/usr/lib/$lib" ]; then
|
||||
cp "$CHROOTDIR/usr/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
else
|
||||
echo "*** Failed to find '$blib'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$STRIP $OUTDIR/usr/lib/$blib
|
||||
done
|
||||
|
||||
echo "Copying local libraries..."
|
||||
for lib in "${DEPLIBS[@]}"; do
|
||||
blib=$(basename "$lib")
|
||||
echo "$DEPSDIR/lib/$lib"
|
||||
if [ -f "$DEPSDIR/lib/$lib" ]; then
|
||||
cp "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
else
|
||||
echo "*** Failed to find '$blib'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$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
|
||||
|
||||
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 -maxdepth 1); do
|
||||
if [ -f "$so" ]; then
|
||||
echo "Patching RPATH in ${so}"
|
||||
patchelf --set-rpath '$ORIGIN' "$so"
|
||||
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"
|
||||
mkdir -p "$OUTDIR/usr/share/icons/hicolor/512x512/apps"
|
||||
cp -v "$SCRIPTDIR/../org.duckstation.DuckStation.desktop" "$OUTDIR/usr/share/applications"
|
||||
cp -v "$SCRIPTDIR/../org.duckstation.DuckStation.png" "$OUTDIR/usr/share/icons/hicolor/512x512/apps"
|
||||
ln -s "usr/share/applications/org.duckstation.DuckStation.desktop" "$OUTDIR"
|
||||
ln -s "usr/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png" "$OUTDIR"
|
||||
|
||||
# Generate AppStream meta-info.
|
||||
echo "Generating AppStream metainfo..."
|
||||
mkdir -p "$OUTDIR/usr/share/metainfo"
|
||||
"$SCRIPTDIR/../generate-metainfo.sh" "$OUTDIR/usr/share/metainfo"
|
||||
|
||||
# Copy AppRun
|
||||
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"
|
||||
fi
|
||||
|
||||
echo "Generating AppImage..."
|
||||
rm -f "$NAME.AppImage"
|
||||
"$APPIMAGETOOL" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$NAME.AppImage"
|
||||
@@ -120,8 +120,8 @@ package() {
|
||||
install -Dm755 scripts/packaging/duckstation-qt "${pkgdir}/usr/bin/duckstation-qt"
|
||||
|
||||
# install desktop file and icon
|
||||
install -Dm644 scripts/${_desktopname}.desktop "${pkgdir}/usr/share/applications/${_desktopname}.desktop"
|
||||
install -Dm644 scripts/${_desktopname}.png "${pkgdir}/usr/share/icons/hicolor/512x512/apps/${_desktopname}.png"
|
||||
install -Dm644 scripts/packaging/${_desktopname}.desktop "${pkgdir}/usr/share/applications/${_desktopname}.desktop"
|
||||
install -Dm644 scripts/packaging/${_desktopname}.png "${pkgdir}/usr/share/icons/hicolor/512x512/apps/${_desktopname}.png"
|
||||
|
||||
# install license
|
||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
||||
|
||||
@@ -71,8 +71,8 @@ ninja -C build %{?_smp_mflags}
|
||||
rm -fr %{buildroot}
|
||||
ninja -C build install
|
||||
install -Dm755 scripts/packaging/duckstation-qt %{buildroot}/usr/bin/duckstation-qt
|
||||
install -Dm644 scripts/org.duckstation.DuckStation.png %{buildroot}/usr/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png
|
||||
install -Dm644 scripts/org.duckstation.DuckStation.desktop %{buildroot}/usr/share/applications/org.duckstation.DuckStation.desktop
|
||||
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
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
|
||||
@@ -26,7 +26,7 @@ build-options:
|
||||
sources:
|
||||
- type: git
|
||||
url: "https://github.com/nih-at/libzip.git"
|
||||
commit: "9c8b818a1de143a4a8ee445351fb8f92115e33e1"
|
||||
commit: "64b62d6b1a686a1b0bac1b6b9dcb635be0499afb"
|
||||
cleanup:
|
||||
- /bin
|
||||
- /include
|
||||
@@ -80,21 +80,21 @@ modules:
|
||||
- "-DCMAKE_SHARED_LINKER_FLAGS_INIT=-fuse-ld=lld"
|
||||
sources:
|
||||
- type: dir
|
||||
path: ../..
|
||||
path: ../../..
|
||||
|
||||
post-install:
|
||||
# Manually copy desktop file/metadata, it's not done as part of the regular build.
|
||||
- >-
|
||||
install -Dm644
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/org.duckstation.DuckStation.png"
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/packaging/org.duckstation.DuckStation.png"
|
||||
"${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png"
|
||||
- >-
|
||||
install -Dm644
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/org.duckstation.DuckStation.desktop"
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/packaging/org.duckstation.DuckStation.desktop"
|
||||
"${FLATPAK_DEST}/share/applications/org.duckstation.DuckStation.desktop"
|
||||
- >-
|
||||
install -Dm644
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/flatpak/org.duckstation.DuckStation.metainfo.xml"
|
||||
"${FLATPAK_BUILDER_BUILDDIR}/scripts/packaging/flatpak/org.duckstation.DuckStation.metainfo.xml"
|
||||
"${FLATPAK_DEST}/share/metainfo/org.duckstation.DuckStation.metainfo.xml"
|
||||
|
||||
# Ensure ffmpeg-full mount point exists.
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
@@ -6,13 +6,12 @@ import subprocess
|
||||
import multiprocessing
|
||||
from functools import partial
|
||||
|
||||
def is_game_path(path):
|
||||
idx = path.rfind('.')
|
||||
if idx < 0:
|
||||
return False
|
||||
|
||||
extension = path[idx + 1:].strip().lower()
|
||||
return extension in ["cue", "chd"]
|
||||
def is_game_path(path:str):
|
||||
lpath = path.lower()
|
||||
for extension in ["cue", "chd", "psxgpu", "psxgpu.zst", "psxgpu.xz"]:
|
||||
if path.endswith(extension):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def run_regression_test(runner, destdir, dump_interval, frames, renderer, cargs, gamepath):
|
||||
@@ -31,8 +30,10 @@ def run_regression_test(runner, destdir, dump_interval, frames, renderer, cargs,
|
||||
return os.path.basename(gamepath)
|
||||
|
||||
|
||||
def run_regression_tests(runner, gamedir, destdir, dump_interval, frames, parallel, renderer, cargs):
|
||||
paths = glob.glob(gamedir + "/*.*", recursive=True)
|
||||
def run_regression_tests(runner, gamedirs, destdir, dump_interval, frames, parallel, renderer, cargs):
|
||||
paths = []
|
||||
for gamedir in gamedirs:
|
||||
paths += glob.glob(os.path.realpath(gamedir) + "/*.*", recursive=True)
|
||||
gamepaths = list(filter(is_game_path, paths))
|
||||
|
||||
try:
|
||||
@@ -64,7 +65,7 @@ def run_regression_tests(runner, gamedir, destdir, dump_interval, frames, parall
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate frame dump images for regression tests")
|
||||
parser.add_argument("-runner", action="store", required=True, help="Path to DuckStation regression test runner")
|
||||
parser.add_argument("-gamedir", action="store", required=True, help="Directory containing game images")
|
||||
parser.add_argument("-gamedir", action="append", required=True, help="Directory containing game images")
|
||||
parser.add_argument("-destdir", action="store", required=True, help="Base directory to dump frames to")
|
||||
parser.add_argument("-dumpinterval", action="store", type=int, default=600, help="Interval to dump frames at")
|
||||
parser.add_argument("-frames", action="store", type=int, default=36000, help="Number of frames to run")
|
||||
@@ -86,7 +87,7 @@ if __name__ == "__main__":
|
||||
if (args.cpu is not None):
|
||||
cargs += ["-cpu", args.cpu]
|
||||
|
||||
if not run_regression_tests(args.runner, os.path.realpath(args.gamedir), os.path.realpath(args.destdir), args.dumpinterval, args.frames, args.parallel, args.renderer, cargs):
|
||||
if not run_regression_tests(args.runner, args.gamedir, os.path.realpath(args.destdir), args.dumpinterval, args.frames, args.parallel, args.renderer, cargs):
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(0)
|
||||
|
||||
@@ -4,6 +4,7 @@ add_executable(common-tests
|
||||
gsvector_yuvtorgb_test.cpp
|
||||
path_tests.cpp
|
||||
rectangle_tests.cpp
|
||||
sha256_tests.cpp
|
||||
string_tests.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<ClCompile Include="file_system_tests.cpp" />
|
||||
<ClCompile Include="path_tests.cpp" />
|
||||
<ClCompile Include="rectangle_tests.cpp" />
|
||||
<ClCompile Include="sha256_tests.cpp" />
|
||||
<ClCompile Include="string_tests.cpp" />
|
||||
<ClCompile Include="gsvector_yuvtorgb_test.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
<ClCompile Include="path_tests.cpp" />
|
||||
<ClCompile Include="string_tests.cpp" />
|
||||
<ClCompile Include="gsvector_yuvtorgb_test.cpp" />
|
||||
<ClCompile Include="sha256_tests.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -15,8 +15,8 @@ static void YUVToRGB_Vector(const std::array<s16, 64>& Crblk, const std::array<s
|
||||
const GSVector4i addval = signed_output ? GSVector4i::cxpr(0) : GSVector4i::cxpr(0x80808080);
|
||||
for (u32 y = 0; y < 8; y++)
|
||||
{
|
||||
const GSVector4i Cr = GSVector4i::loadl(&Crblk[(y / 2) * 8]).s16to32();
|
||||
const GSVector4i Cb = GSVector4i::loadl(&Cbblk[(y / 2) * 8]).s16to32();
|
||||
const GSVector4i Cr = GSVector4i::loadl<false>(&Crblk[(y / 2) * 8]).s16to32();
|
||||
const GSVector4i Cb = GSVector4i::loadl<false>(&Cbblk[(y / 2) * 8]).s16to32();
|
||||
const GSVector4i Y = GSVector4i::load<true>(&Yblk[y * 8]);
|
||||
|
||||
// BT.601 YUV->RGB coefficients, rounding formula from Mednafen.
|
||||
|
||||
@@ -78,3 +78,59 @@ TEST(Rectangle, RelationalOperators)
|
||||
ASSERT_FALSE(r1.eq(r2));
|
||||
}
|
||||
|
||||
TEST(Rectangle, ValidRectangles)
|
||||
{
|
||||
static constexpr GSVector4i cases[] = {
|
||||
GSVector4i::cxpr(1, 2, 3, 4),
|
||||
GSVector4i::cxpr(-5, -10, -1, -2),
|
||||
GSVector4i::cxpr(0, 0, 1, 1),
|
||||
GSVector4i::cxpr(100, 200, 300, 400),
|
||||
GSVector4i::cxpr(-1000, -2000, 500, 600),
|
||||
GSVector4i::cxpr(5, 10, 6, 12),
|
||||
GSVector4i::cxpr(-10, -20, -5, -15),
|
||||
GSVector4i::cxpr(-5, 0, 5, 10),
|
||||
GSVector4i::cxpr(-100, -200, 100, 200),
|
||||
GSVector4i::cxpr(-1, -2, 0, 1),
|
||||
};
|
||||
|
||||
for (GSVector4i tcase : cases)
|
||||
{
|
||||
ASSERT_TRUE(tcase.rvalid());
|
||||
ASSERT_FALSE(tcase.rempty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Rectangle, InvalidRectangles)
|
||||
{
|
||||
static constexpr GSVector4i cases[] = {
|
||||
// left < right but not top < bottom
|
||||
GSVector4i::cxpr(1, 4, 3, 2),
|
||||
GSVector4i::cxpr(-5, -2, -1, -10),
|
||||
GSVector4i::cxpr(0, 1, 1, 0),
|
||||
GSVector4i::cxpr(100, 400, 300, 200),
|
||||
GSVector4i::cxpr(-1000, 600, 500, -2000),
|
||||
GSVector4i::cxpr(5, 12, 6, 10),
|
||||
GSVector4i::cxpr(-10, -15, -5, -20),
|
||||
GSVector4i::cxpr(-5, 10, 5, 0),
|
||||
GSVector4i::cxpr(-100, 200, 100, -200),
|
||||
GSVector4i::cxpr(-1, 1, 0, -2),
|
||||
|
||||
// not left < right but top < bottom
|
||||
GSVector4i::cxpr(3, 2, 1, 4),
|
||||
GSVector4i::cxpr(-1, -10, -5, -2),
|
||||
GSVector4i::cxpr(1, 0, 0, 1),
|
||||
GSVector4i::cxpr(300, 200, 100, 400),
|
||||
GSVector4i::cxpr(500, -2000, -1000, 600),
|
||||
GSVector4i::cxpr(6, 10, 5, 12),
|
||||
GSVector4i::cxpr(-5, -20, -10, -15),
|
||||
GSVector4i::cxpr(5, 0, -5, 10),
|
||||
GSVector4i::cxpr(100, -200, -100, 200),
|
||||
GSVector4i::cxpr(0, -2, -1, 1),
|
||||
};
|
||||
|
||||
for (GSVector4i tcase : cases)
|
||||
{
|
||||
ASSERT_FALSE(tcase.rvalid());
|
||||
ASSERT_TRUE(tcase.rempty());
|
||||
}
|
||||
}
|
||||
|
||||
34
src/common-tests/sha256_tests.cpp
Normal file
34
src/common-tests/sha256_tests.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "common/sha256_digest.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(SHA256Digest, Simple)
|
||||
{
|
||||
// https://github.com/B-Con/crypto-algorithms/blob/master/sha256_test.c
|
||||
|
||||
static constexpr const char text1[] = "abc";
|
||||
static constexpr const char text2[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
static constexpr const char text3[] = "aaaaaaaaaa";
|
||||
|
||||
static constexpr SHA256Digest::Digest hash1 = {{0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40,
|
||||
0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17,
|
||||
0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}};
|
||||
static constexpr SHA256Digest::Digest hash2 = {{0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
|
||||
0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
|
||||
0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}};
|
||||
static constexpr SHA256Digest::Digest hash3 = {{0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7,
|
||||
0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97,
|
||||
0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0}};
|
||||
|
||||
ASSERT_EQ(SHA256Digest::GetDigest(text1, std::size(text1) - 1), hash1);
|
||||
ASSERT_EQ(SHA256Digest::GetDigest(text2, std::size(text2) - 1), hash2);
|
||||
|
||||
SHA256Digest ldigest;
|
||||
for (u32 i = 0; i < 100000; i++)
|
||||
ldigest.Update(text3, std::size(text3) - 1);
|
||||
|
||||
ASSERT_EQ(ldigest.Final(), hash3);
|
||||
}
|
||||
@@ -33,3 +33,41 @@ TEST(StringUtil, EllipsiseInPlace)
|
||||
StringUtil::EllipsiseInPlace(s, 10, "...");
|
||||
ASSERT_EQ(s, "Hello");
|
||||
}
|
||||
|
||||
TEST(StringUtil, Base64EncodeDecode)
|
||||
{
|
||||
struct TestCase
|
||||
{
|
||||
const char* hexString;
|
||||
const char* base64String;
|
||||
};
|
||||
static const TestCase testCases[] = {
|
||||
{"33326a6f646933326a68663937683732383368", "MzJqb2RpMzJqaGY5N2g3MjgzaA=="},
|
||||
{"32753965333268756979386672677537366967723839683432703075693132393065755c5d0931325c335c31323439303438753839333272",
|
||||
"MnU5ZTMyaHVpeThmcmd1NzZpZ3I4OWg0MnAwdWkxMjkwZXVcXQkxMlwzXDEyNDkwNDh1ODkzMnI="},
|
||||
{"3332726a33323738676838666233326830393233386637683938323139", "MzJyajMyNzhnaDhmYjMyaDA5MjM4ZjdoOTgyMTk="},
|
||||
{"9956967BE9C96E10B27FF8897A5B768A2F4B103CE934718D020FE6B5B770", "mVaWe+nJbhCyf/iJelt2ii9LEDzpNHGNAg/mtbdw"},
|
||||
{"BC94251814827A5D503D62D5EE6CBAB0FD55D2E2FCEDBB2261D6010084B95DD648766D8983F03AFA3908956D8201E26BB09FE52B515A61A9E"
|
||||
"1D3ADC207BD9E622128F22929CDED456B595A410F7168B0BA6370289E6291E38E47C18278561C79A7297C21D23C06BB2F694DC2F65FAAF994"
|
||||
"59E3FC14B1FA415A3320AF00ACE54C00BE",
|
||||
"vJQlGBSCel1QPWLV7my6sP1V0uL87bsiYdYBAIS5XdZIdm2Jg/A6+jkIlW2CAeJrsJ/"
|
||||
"lK1FaYanh063CB72eYiEo8ikpze1Fa1laQQ9xaLC6Y3AonmKR445HwYJ4Vhx5pyl8IdI8BrsvaU3C9l+q+ZRZ4/wUsfpBWjMgrwCs5UwAvg=="},
|
||||
{"192B42CB0F66F69BE8A5", "GStCyw9m9pvopQ=="},
|
||||
{"38ABD400F3BB6960EB60C056719B5362", "OKvUAPO7aWDrYMBWcZtTYg=="},
|
||||
{"776FAB27DC7F8DA86F298D55B69F8C278D53871F8CBCCF", "d2+rJ9x/jahvKY1Vtp+MJ41Thx+MvM8="},
|
||||
{"B1ED3EA2E35EE69C7E16707B05042A", "se0+ouNe5px+FnB7BQQq"},
|
||||
};
|
||||
|
||||
for (const TestCase& tc : testCases)
|
||||
{
|
||||
std::optional<std::vector<u8>> bytes = StringUtil::DecodeHex(tc.hexString);
|
||||
ASSERT_TRUE(bytes.has_value());
|
||||
|
||||
std::string encoded_b64 = StringUtil::EncodeBase64(bytes.value());
|
||||
ASSERT_EQ(encoded_b64, tc.base64String);
|
||||
|
||||
std::optional<std::vector<u8>> dbytes = StringUtil::DecodeBase64(tc.base64String);
|
||||
ASSERT_TRUE(dbytes.has_value());
|
||||
ASSERT_EQ(dbytes.value(), bytes.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,12 +50,18 @@ add_library(common
|
||||
settings_interface.h
|
||||
sha1_digest.cpp
|
||||
sha1_digest.h
|
||||
sha256_digest.cpp
|
||||
sha256_digest.h
|
||||
small_string.cpp
|
||||
small_string.h
|
||||
string_util.cpp
|
||||
string_util.h
|
||||
thirdparty/SmallVector.cpp
|
||||
thirdparty/SmallVector.h
|
||||
thirdparty/aes.cpp
|
||||
thirdparty/aes.h
|
||||
task_queue.cpp
|
||||
task_queue.h
|
||||
threading.cpp
|
||||
threading.h
|
||||
timer.cpp
|
||||
|
||||
@@ -58,14 +58,17 @@ constexpr T PreviousPow2(T value)
|
||||
value |= (value >> 1);
|
||||
value |= (value >> 2);
|
||||
value |= (value >> 4);
|
||||
if constexpr (sizeof(T) >= 16)
|
||||
if constexpr (sizeof(T) >= 2)
|
||||
value |= (value >> 8);
|
||||
if constexpr (sizeof(T) >= 32)
|
||||
if constexpr (sizeof(T) >= 4)
|
||||
value |= (value >> 16);
|
||||
if constexpr (sizeof(T) >= 64)
|
||||
if constexpr (sizeof(T) >= 8)
|
||||
value |= (value >> 32);
|
||||
return value - (value >> 1);
|
||||
|
||||
return (value >> 1) + 1;
|
||||
}
|
||||
|
||||
/// NOTE: Undefined for values greater than (1 << BITS-1), i.e. 0x80000000 for 32-bit.
|
||||
template<typename T>
|
||||
constexpr T NextPow2(T value)
|
||||
{
|
||||
@@ -77,11 +80,11 @@ constexpr T NextPow2(T value)
|
||||
value |= (value >> 1);
|
||||
value |= (value >> 2);
|
||||
value |= (value >> 4);
|
||||
if constexpr (sizeof(T) >= 16)
|
||||
if constexpr (sizeof(T) >= 2)
|
||||
value |= (value >> 8);
|
||||
if constexpr (sizeof(T) >= 32)
|
||||
if constexpr (sizeof(T) >= 4)
|
||||
value |= (value >> 16);
|
||||
if constexpr (sizeof(T) >= 64)
|
||||
if constexpr (sizeof(T) >= 8)
|
||||
value |= (value >> 32);
|
||||
value++;
|
||||
return value;
|
||||
|
||||
@@ -3,15 +3,17 @@
|
||||
|
||||
#include "assert.h"
|
||||
#include "crash_handler.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "windows_headers.h"
|
||||
#include <intrin.h>
|
||||
#include <tlhelp32.h>
|
||||
#endif
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Winvalid-noreturn"
|
||||
@@ -19,9 +21,8 @@
|
||||
|
||||
static std::mutex s_AssertFailedMutex;
|
||||
|
||||
static inline void FreezeThreads(void** ppHandle)
|
||||
static HANDLE FreezeThreads()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (hSnapshot != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -43,17 +44,12 @@ static inline void FreezeThreads(void** ppHandle)
|
||||
}
|
||||
}
|
||||
|
||||
*ppHandle = (void*)hSnapshot;
|
||||
#else
|
||||
*ppHandle = nullptr;
|
||||
#endif
|
||||
return hSnapshot;
|
||||
}
|
||||
|
||||
static inline void ResumeThreads(void* pHandle)
|
||||
static void ResumeThreads(HANDLE hSnapshot)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
HANDLE hSnapshot = (HANDLE)pHandle;
|
||||
if (pHandle != INVALID_HANDLE_VALUE)
|
||||
if (hSnapshot != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 threadEntry;
|
||||
if (Thread32First(hSnapshot, &threadEntry))
|
||||
@@ -73,21 +69,42 @@ static inline void ResumeThreads(void* pHandle)
|
||||
}
|
||||
CloseHandle(hSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Define as a weak symbol for ancient devices that don't have it.
|
||||
extern "C" __attribute__((weak)) void android_set_abort_message(const char*);
|
||||
#endif
|
||||
|
||||
[[noreturn]] ALWAYS_INLINE static void AbortWithMessage(const char* szMsg)
|
||||
{
|
||||
#ifndef __ANDROID__
|
||||
std::fputs(szMsg, stderr);
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
std::fputs("Aborting application.\n", stderr);
|
||||
std::fflush(stderr);
|
||||
std::abort();
|
||||
#else
|
||||
if (&android_set_abort_message)
|
||||
android_set_abort_message(szMsg);
|
||||
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char* szFile, unsigned uLine)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_AssertFailedMutex);
|
||||
|
||||
void* pHandle;
|
||||
FreezeThreads(&pHandle);
|
||||
|
||||
char szMsg[512];
|
||||
std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)\n", szMessage, szFunction, szFile, uLine);
|
||||
|
||||
#if defined(_WIN32)
|
||||
std::unique_lock lock(s_AssertFailedMutex);
|
||||
HANDLE pHandle = FreezeThreads();
|
||||
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
||||
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL);
|
||||
OutputDebugStringA(szMsg);
|
||||
@@ -107,28 +124,22 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
TerminateProcess(GetCurrentProcess(), 0xBAADC0DE);
|
||||
}
|
||||
#else
|
||||
std::fputs(szMsg, stderr);
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
std::fputs("Aborting application.\n", stderr);
|
||||
std::fflush(stderr);
|
||||
std::abort();
|
||||
#endif
|
||||
|
||||
ResumeThreads(pHandle);
|
||||
#else
|
||||
AbortWithMessage(szMsg);
|
||||
#endif
|
||||
}
|
||||
|
||||
[[noreturn]] void Y_OnPanicReached(const char* szMessage, const char* szFunction, const char* szFile, unsigned uLine)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(s_AssertFailedMutex);
|
||||
|
||||
void* pHandle;
|
||||
FreezeThreads(&pHandle);
|
||||
|
||||
char szMsg[512];
|
||||
std::snprintf(szMsg, sizeof(szMsg), "%s in function %s (%s:%u)\n", szMessage, szFunction, szFile, uLine);
|
||||
|
||||
#if defined(_WIN32)
|
||||
std::unique_lock guard(s_AssertFailedMutex);
|
||||
HANDLE pHandle = FreezeThreads();
|
||||
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
||||
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), szMsg, static_cast<DWORD>(std::strlen(szMsg)), NULL, NULL);
|
||||
OutputDebugStringA(szMsg);
|
||||
@@ -145,13 +156,9 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
|
||||
TerminateProcess(GetCurrentProcess(), 0xBAADC0DE);
|
||||
#else
|
||||
std::fputs(szMsg, stderr);
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
std::fputs("Aborting application.\n", stderr);
|
||||
std::fflush(stderr);
|
||||
std::abort();
|
||||
#endif
|
||||
|
||||
ResumeThreads(pHandle);
|
||||
#else
|
||||
AbortWithMessage(szMsg);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -9,27 +9,31 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
||||
[[noreturn]] void Y_OnPanicReached(const char* szMessage, const char* szFunction, const char* szFile, unsigned uLine);
|
||||
|
||||
#define Assert(expr) \
|
||||
if (!(expr)) \
|
||||
do \
|
||||
{ \
|
||||
Y_OnAssertFailed("Assertion failed: '" #expr "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
}
|
||||
if (!(expr)) \
|
||||
Y_OnAssertFailed("Assertion failed: '" #expr "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#define AssertMsg(expr, msg) \
|
||||
if (!(expr)) \
|
||||
do \
|
||||
{ \
|
||||
Y_OnAssertFailed("Assertion failed: '" msg "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
}
|
||||
if (!(expr)) \
|
||||
Y_OnAssertFailed("Assertion failed: '" msg "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
#define DebugAssert(expr) \
|
||||
if (!(expr)) \
|
||||
do \
|
||||
{ \
|
||||
Y_OnAssertFailed("Debug assertion failed: '" #expr "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
}
|
||||
if (!(expr)) \
|
||||
Y_OnAssertFailed("Debug assertion failed: '" #expr "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#define DebugAssertMsg(expr, msg) \
|
||||
if (!(expr)) \
|
||||
do \
|
||||
{ \
|
||||
Y_OnAssertFailed("Debug assertion failed: '" msg "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
}
|
||||
if (!(expr)) \
|
||||
Y_OnAssertFailed("Debug assertion failed: '" msg "'", __FUNCTION__, __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DebugAssert(expr)
|
||||
#define DebugAssertMsg(expr, msg)
|
||||
@@ -41,7 +45,7 @@ void Y_OnAssertFailed(const char* szMessage, const char* szFunction, const char*
|
||||
// Kills the application, indicating a pure function call that should not have happened.
|
||||
#define PureCall() Y_OnPanicReached("PureCall encountered", __FUNCTION__, __FILE__, __LINE__)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(_DEBUG) || defined(_DEVEL)
|
||||
// Kills the application, indicating that code that was never supposed to be reached has been executed.
|
||||
#define UnreachableCode() Y_OnPanicReached("Unreachable code reached", __FUNCTION__, __FILE__, __LINE__)
|
||||
#else
|
||||
|
||||
@@ -36,13 +36,16 @@
|
||||
<ClInclude Include="scoped_guard.h" />
|
||||
<ClInclude Include="settings_interface.h" />
|
||||
<ClInclude Include="sha1_digest.h" />
|
||||
<ClInclude Include="sha256_digest.h" />
|
||||
<ClInclude Include="small_string.h" />
|
||||
<ClInclude Include="heterogeneous_containers.h" />
|
||||
<ClInclude Include="binary_reader_writer.h" />
|
||||
<ClInclude Include="string_util.h" />
|
||||
<ClInclude Include="thirdparty\aes.h" />
|
||||
<ClInclude Include="thirdparty\SmallVector.h" />
|
||||
<ClInclude Include="thirdparty\StackWalker.h" />
|
||||
<ClInclude Include="threading.h" />
|
||||
<ClInclude Include="task_queue.h" />
|
||||
<ClInclude Include="timer.h" />
|
||||
<ClInclude Include="types.h" />
|
||||
<ClInclude Include="minizip_helpers.h" />
|
||||
@@ -64,12 +67,15 @@
|
||||
<ClCompile Include="perf_scope.cpp" />
|
||||
<ClCompile Include="progress_callback.cpp" />
|
||||
<ClCompile Include="sha1_digest.cpp" />
|
||||
<ClCompile Include="sha256_digest.cpp" />
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
<ClCompile Include="binary_reader_writer.cpp" />
|
||||
<ClCompile Include="string_util.cpp" />
|
||||
<ClCompile Include="thirdparty\aes.cpp" />
|
||||
<ClCompile Include="thirdparty\SmallVector.cpp" />
|
||||
<ClCompile Include="thirdparty\StackWalker.cpp" />
|
||||
<ClCompile Include="threading.cpp" />
|
||||
<ClCompile Include="task_queue.cpp" />
|
||||
<ClCompile Include="timer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
<ClInclude Include="gsvector_nosimd.h" />
|
||||
<ClInclude Include="ryml_helpers.h" />
|
||||
<ClInclude Include="log_channels.h" />
|
||||
<ClInclude Include="sha256_digest.h" />
|
||||
<ClInclude Include="thirdparty\aes.h" />
|
||||
<ClInclude Include="task_queue.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
@@ -78,6 +81,9 @@
|
||||
<ClCompile Include="dynamic_library.cpp" />
|
||||
<ClCompile Include="binary_reader_writer.cpp" />
|
||||
<ClCompile Include="gsvector.cpp" />
|
||||
<ClCompile Include="sha256_digest.cpp" />
|
||||
<ClCompile Include="thirdparty\aes.cpp" />
|
||||
<ClCompile Include="task_queue.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="bitfield.natvis" />
|
||||
|
||||
@@ -367,7 +367,7 @@ void CrashHandler::WriteDumpForCaller()
|
||||
LogCallstack(0, nullptr);
|
||||
}
|
||||
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
|
||||
bool CrashHandler::Install(CleanupHandler cleanup_handler)
|
||||
{
|
||||
|
||||
@@ -141,6 +141,6 @@ private:
|
||||
void AddPrefixFmtArgs(fmt::string_view fmt, fmt::format_args args);
|
||||
void AddSuffixFmtArgs(fmt::string_view fmt, fmt::format_args args);
|
||||
|
||||
Type m_type = Type::None;
|
||||
std::string m_description;
|
||||
Type m_type = Type::None;
|
||||
};
|
||||
|
||||
@@ -12,13 +12,14 @@
|
||||
#define PREFIX ""
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
asm("\t.global " PREFIX "fastjmp_set\n"
|
||||
"\t.global " PREFIX "fastjmp_jmp\n"
|
||||
"\t.text\n"
|
||||
"\t" PREFIX "fastjmp_set:"
|
||||
R"(
|
||||
"\t.global " PREFIX "fastjmp_jmp\n"
|
||||
"\t.text\n"
|
||||
"\t" PREFIX "fastjmp_set:" R"(
|
||||
movq 0(%rsp), %rax
|
||||
movq %rsp, %rdx # fixup stack pointer, so it doesn't include the call to fastjmp_set
|
||||
addq $8, %rdx
|
||||
@@ -33,8 +34,7 @@ asm("\t.global " PREFIX "fastjmp_set\n"
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
)"
|
||||
"\t" PREFIX "fastjmp_jmp:"
|
||||
R"(
|
||||
"\t" PREFIX "fastjmp_jmp:" R"(
|
||||
movl %esi, %eax
|
||||
movq 0(%rdi), %rdx # actually rip
|
||||
movq 8(%rdi), %rbx
|
||||
@@ -95,20 +95,20 @@ asm(
|
||||
"\t.global " PREFIX "fastjmp_jmp\n"
|
||||
"\t.text\n"
|
||||
"\t" PREFIX "fastjmp_set:" R"(
|
||||
vstmia r0!, {d8-d15}
|
||||
stmia r0!, {r4-r14}
|
||||
fmrx r1, fpscr
|
||||
str r1, [r0]
|
||||
mov r0, #0
|
||||
bx lr
|
||||
vstmia r0!, {d8-d15}
|
||||
stmia r0!, {r4-r14}
|
||||
fmrx r1, fpscr
|
||||
str r1, [r0]
|
||||
mov r0, #0
|
||||
bx lr
|
||||
)"
|
||||
|
||||
"\t" PREFIX "fastjmp_jmp:" R"(
|
||||
vldmia r0!, {d8-d15}
|
||||
ldmia r0!, {r4-r14}
|
||||
vldmia r0!, {d8-d15}
|
||||
ldmia r0!, {r4-r14}
|
||||
ldr r0, [r0]
|
||||
fmxr fpscr, r0
|
||||
mov r0, r1
|
||||
mov r0, r1
|
||||
bx lr
|
||||
)");
|
||||
|
||||
@@ -117,68 +117,69 @@ asm(
|
||||
asm(
|
||||
"\t.global " PREFIX "fastjmp_set\n"
|
||||
"\t.global " PREFIX "fastjmp_jmp\n"
|
||||
"\t.attribute arch, \"rv64gc\"\n"
|
||||
"\t.text\n"
|
||||
"\t.align 16\n"
|
||||
"\t" PREFIX "fastjmp_set:" R"(
|
||||
sd sp, 0(a0)
|
||||
sd s0, 8(a0)
|
||||
sd s1, 16(a0)
|
||||
sd s2, 24(a0)
|
||||
sd s3, 32(a0)
|
||||
sd s4, 40(a0)
|
||||
sd s5, 48(a0)
|
||||
sd s6, 56(a0)
|
||||
sd s7, 64(a0)
|
||||
sd s8, 72(a0)
|
||||
sd s9, 80(a0)
|
||||
sd s10, 88(a0)
|
||||
sd s11, 96(a0)
|
||||
fsd fs0, 104(a0)
|
||||
fsd fs1, 112(a0)
|
||||
fsd fs2, 120(a0)
|
||||
fsd fs3, 128(a0)
|
||||
fsd fs4, 136(a0)
|
||||
fsd fs5, 144(a0)
|
||||
fsd fs6, 152(a0)
|
||||
fsd fs7, 160(a0)
|
||||
fsd fs8, 168(a0)
|
||||
fsd fs9, 176(a0)
|
||||
fsd fs10, 184(a0)
|
||||
fsd fs11, 192(a0)
|
||||
sd ra, 208(a0)
|
||||
li a0, 0
|
||||
jr ra
|
||||
sd sp, 0(a0)
|
||||
sd s0, 8(a0)
|
||||
sd s1, 16(a0)
|
||||
sd s2, 24(a0)
|
||||
sd s3, 32(a0)
|
||||
sd s4, 40(a0)
|
||||
sd s5, 48(a0)
|
||||
sd s6, 56(a0)
|
||||
sd s7, 64(a0)
|
||||
sd s8, 72(a0)
|
||||
sd s9, 80(a0)
|
||||
sd s10, 88(a0)
|
||||
sd s11, 96(a0)
|
||||
fsd fs0, 104(a0)
|
||||
fsd fs1, 112(a0)
|
||||
fsd fs2, 120(a0)
|
||||
fsd fs3, 128(a0)
|
||||
fsd fs4, 136(a0)
|
||||
fsd fs5, 144(a0)
|
||||
fsd fs6, 152(a0)
|
||||
fsd fs7, 160(a0)
|
||||
fsd fs8, 168(a0)
|
||||
fsd fs9, 176(a0)
|
||||
fsd fs10, 184(a0)
|
||||
fsd fs11, 192(a0)
|
||||
sd ra, 208(a0)
|
||||
li a0, 0
|
||||
jr ra
|
||||
)"
|
||||
".align 16\n"
|
||||
"\t" PREFIX "fastjmp_jmp:" R"(
|
||||
ld ra, 208(a0)
|
||||
fld fs11, 192(a0)
|
||||
fld fs10, 184(a0)
|
||||
fld fs9, 176(a0)
|
||||
fld fs8, 168(a0)
|
||||
fld fs7, 160(a0)
|
||||
fld fs6, 152(a0)
|
||||
fld fs5, 144(a0)
|
||||
fld fs4, 136(a0)
|
||||
fld fs3, 128(a0)
|
||||
fld fs2, 120(a0)
|
||||
fld fs1, 112(a0)
|
||||
fld fs0, 104(a0)
|
||||
ld s11, 96(a0)
|
||||
ld s10, 88(a0)
|
||||
ld s9, 80(a0)
|
||||
ld s8, 72(a0)
|
||||
ld s7, 64(a0)
|
||||
ld s6, 56(a0)
|
||||
ld s5, 48(a0)
|
||||
ld s4, 40(a0)
|
||||
ld s3, 32(a0)
|
||||
ld s2, 24(a0)
|
||||
ld s1, 16(a0)
|
||||
ld s0, 8(a0)
|
||||
ld sp, 0(a0)
|
||||
mv a0, a1
|
||||
jr ra
|
||||
ld ra, 208(a0)
|
||||
fld fs11, 192(a0)
|
||||
fld fs10, 184(a0)
|
||||
fld fs9, 176(a0)
|
||||
fld fs8, 168(a0)
|
||||
fld fs7, 160(a0)
|
||||
fld fs6, 152(a0)
|
||||
fld fs5, 144(a0)
|
||||
fld fs4, 136(a0)
|
||||
fld fs3, 128(a0)
|
||||
fld fs2, 120(a0)
|
||||
fld fs1, 112(a0)
|
||||
fld fs0, 104(a0)
|
||||
ld s11, 96(a0)
|
||||
ld s10, 88(a0)
|
||||
ld s9, 80(a0)
|
||||
ld s8, 72(a0)
|
||||
ld s7, 64(a0)
|
||||
ld s6, 56(a0)
|
||||
ld s5, 48(a0)
|
||||
ld s4, 40(a0)
|
||||
ld s3, 32(a0)
|
||||
ld s2, 24(a0)
|
||||
ld s1, 16(a0)
|
||||
ld s0, 8(a0)
|
||||
ld sp, 0(a0)
|
||||
mv a0, a1
|
||||
jr ra
|
||||
)");
|
||||
|
||||
|
||||
@@ -188,4 +189,6 @@ asm(
|
||||
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // __WIN32
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user