mirror of
https://github.com/flyinghead/flycast.git
synced 2026-11-08 01:48:31 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1f0a5a15f | ||
|
|
f640b32cc9 | ||
|
|
93e47dd410 | ||
|
|
8fb3def2d5 | ||
|
|
98a0f2b821 | ||
|
|
4fafa91506 | ||
|
|
09a1fea40f | ||
|
|
e55d70c0e6 | ||
|
|
ca45ff3834 | ||
|
|
35c71ebcfd | ||
|
|
33edcca348 | ||
|
|
dac5b991e0 | ||
|
|
8ba5e05421 | ||
|
|
35b7be3905 | ||
|
|
b7d923e02b | ||
|
|
eaf2c0064c | ||
|
|
a65cd9e5f9 | ||
|
|
e94b26f1df | ||
|
|
e96b38ff5c | ||
|
|
e894d4df5c | ||
|
|
c58ae4daac | ||
|
|
cb9af7d742 | ||
|
|
2a364dee67 | ||
|
|
56107b3667 | ||
|
|
31aab32d95 | ||
|
|
0b66409ed2 | ||
|
|
8ae288d2ca | ||
|
|
4419ff310a | ||
|
|
2f524923da | ||
|
|
07d761a880 | ||
|
|
f6f6637973 | ||
|
|
2cd3ffb33f | ||
|
|
abd9219347 | ||
|
|
417a42ae10 | ||
|
|
0e12153c45 | ||
|
|
cb33387ed6 | ||
|
|
38d4689b63 | ||
|
|
23d1db9c75 | ||
|
|
4e079b5d0b | ||
|
|
3fcbdd3fc5 | ||
|
|
78b44919c5 | ||
|
|
13a8d49c90 | ||
|
|
7308f9a704 | ||
|
|
18f9b84af6 | ||
|
|
56517b027a | ||
|
|
d4a02e3c2b | ||
|
|
33131e1395 | ||
|
|
73ac46f421 | ||
|
|
7fc70ee1f4 | ||
|
|
d9b5f27311 | ||
|
|
252838d896 | ||
|
|
cb91ad3ae0 | ||
|
|
60f3d718ac | ||
|
|
e8e382372a | ||
|
|
205c365b1b | ||
|
|
09857008bd | ||
|
|
5eddc26850 | ||
|
|
496429d6f4 | ||
|
|
a915f185f8 | ||
|
|
0f6e1752e3 | ||
|
|
e57ccde532 | ||
|
|
f75a16f40c | ||
|
|
a869e183db | ||
|
|
c60edb0090 | ||
|
|
84d82f360b | ||
|
|
b002bdff39 | ||
|
|
5ffcdb5f1e | ||
|
|
79bbd86c2f | ||
|
|
39a212140a | ||
|
|
dddd712f08 | ||
|
|
a7dbbbe578 | ||
|
|
2445739c0e | ||
|
|
403f1f635b | ||
|
|
879372cb79 | ||
|
|
6b05c0ab01 | ||
|
|
289f264371 | ||
|
|
869ddb643d | ||
|
|
c63f1a9997 | ||
|
|
0fc0dc5101 | ||
|
|
213bc70e2d | ||
|
|
c839bc89eb | ||
|
|
84f2871650 | ||
|
|
e1b4d4d703 | ||
|
|
b564b0bf91 | ||
|
|
7e1dcf9003 | ||
|
|
0f4c903fed | ||
|
|
0ac483acfc | ||
|
|
f4835a89d3 | ||
|
|
139f248572 | ||
|
|
b23d37f76f | ||
|
|
56358be542 | ||
|
|
1377e61d03 | ||
|
|
ce694ba8b5 | ||
|
|
8eae6b97fc | ||
|
|
d29645cc49 | ||
|
|
f870ccc23c | ||
|
|
3aa2f922e7 | ||
|
|
129fff1c2a | ||
|
|
10b13dfe9c | ||
|
|
d506cc40a2 | ||
|
|
358a54152b | ||
|
|
06e2c455e8 | ||
|
|
a1838eee30 | ||
|
|
56b082def7 | ||
|
|
92a10ba0f0 | ||
|
|
c637ae8281 | ||
|
|
40953b17c4 | ||
|
|
a473154250 | ||
|
|
13f3c3e228 | ||
|
|
817cc87c8c | ||
|
|
ab09efa762 | ||
|
|
7061c043d9 | ||
|
|
92a19e9250 | ||
|
|
4f5fd31d81 | ||
|
|
1b565f9879 | ||
|
|
d2b475ae41 | ||
|
|
9c61006941 | ||
|
|
4db26bc092 | ||
|
|
8c0f543bc8 | ||
|
|
8e3a48eb6f | ||
|
|
7a22318b0f | ||
|
|
a0bf24f7cc | ||
|
|
3c6eaa4d34 | ||
|
|
3bf817aea1 | ||
|
|
a3ebe02f85 | ||
|
|
4eda9ebffc | ||
|
|
278f26aadd | ||
|
|
17b82ab5d3 | ||
|
|
30e66d1c17 | ||
|
|
2089015221 | ||
|
|
e19a62aa07 | ||
|
|
42d003597e | ||
|
|
f9da57d87f | ||
|
|
daf8230cca | ||
|
|
f02265b662 | ||
|
|
5eb893a995 | ||
|
|
dfd517706a | ||
|
|
b47f4f56ef | ||
|
|
a870fb7f6c | ||
|
|
7cd308fcae | ||
|
|
6e6f75386b | ||
|
|
aad4921e09 | ||
|
|
8b8113b482 | ||
|
|
98acd1178d | ||
|
|
0070f9abad | ||
|
|
dca048981f | ||
|
|
74b98d85ed | ||
|
|
67a7637b9f | ||
|
|
2511a19d2d | ||
|
|
f04ddad94f | ||
|
|
b4e5af6346 | ||
|
|
f679fd9ba9 | ||
|
|
b6930a2a9e | ||
|
|
4db7137dbf | ||
|
|
bee534922b | ||
|
|
d6fe46649c | ||
|
|
236539c881 | ||
|
|
2644c2ef47 | ||
|
|
f590766421 | ||
|
|
fa1c62d11a | ||
|
|
ffc0a42c18 | ||
|
|
bc3c1ab628 | ||
|
|
6c249ee4d2 | ||
|
|
3330f01267 | ||
|
|
bd946bfbea | ||
|
|
bb92e9f7a4 | ||
|
|
63686eeee1 | ||
|
|
c0a286532a | ||
|
|
ce0354f294 | ||
|
|
231a1b624f | ||
|
|
9b8fd39d12 | ||
|
|
90c4e42c11 | ||
|
|
ee806bc035 | ||
|
|
d76611730e | ||
|
|
bdd677d66a | ||
|
|
2299c9fade | ||
|
|
885714e883 | ||
|
|
f95c7212bf | ||
|
|
bb0da9488f | ||
|
|
1aeacb0297 | ||
|
|
b92b7a3ece | ||
|
|
0a1fe0135f | ||
|
|
4391058563 | ||
|
|
ea9bdd03e4 | ||
|
|
ed99c96232 | ||
|
|
755e17dc97 | ||
|
|
76af42ae6e | ||
|
|
e94babe57e | ||
|
|
416e4c5366 | ||
|
|
6b9840268f | ||
|
|
415d8c2ea3 | ||
|
|
3f456c6738 | ||
|
|
59480ea5a6 | ||
|
|
920666bc70 | ||
|
|
eebcb322cf | ||
|
|
04b0489ff3 | ||
|
|
dd5f44ff91 | ||
|
|
a7b89ba06a | ||
|
|
e5344d37d0 | ||
|
|
c07f862ef2 | ||
|
|
8b0add47a2 | ||
|
|
fe9ce46ab1 | ||
|
|
01c5c98396 | ||
|
|
d00f07acb8 | ||
|
|
83bfa9158d | ||
|
|
ac2637286b | ||
|
|
541544292a | ||
|
|
97bd3fc082 | ||
|
|
71ce2a2415 | ||
|
|
4b0d377e66 | ||
|
|
ae2bc8182f | ||
|
|
d9ec14e048 | ||
|
|
c0f0a758df | ||
|
|
06270e66c8 | ||
|
|
75fe707de3 | ||
|
|
1a5a2f64d4 | ||
|
|
220fd51b27 | ||
|
|
29cdc77817 | ||
|
|
483c59f2e4 | ||
|
|
1fdab613fd | ||
|
|
539b9e7746 | ||
|
|
045f693eef | ||
|
|
3192f84576 | ||
|
|
27038d4cf9 | ||
|
|
4acb670b88 | ||
|
|
79b9b49218 | ||
|
|
5f161df06b | ||
|
|
fc3b9046d8 | ||
|
|
754d2a53a0 | ||
|
|
e913bae9e3 | ||
|
|
22d228c1b0 | ||
|
|
d3a3cab425 | ||
|
|
1fe7352ed0 | ||
|
|
9d1a5cf0d3 | ||
|
|
c8a45d95a7 | ||
|
|
92a1c1891b | ||
|
|
858174791f | ||
|
|
fb4e653269 | ||
|
|
210100a108 | ||
|
|
edd1487378 | ||
|
|
68f4ce1ec5 | ||
|
|
c3c355a8c5 | ||
|
|
70d3e221a9 | ||
|
|
b556617e1d | ||
|
|
e327172fd0 | ||
|
|
c5f82483e6 | ||
|
|
a418b05272 | ||
|
|
5c3f66fe05 | ||
|
|
81ce3f7d10 | ||
|
|
64cfba735e | ||
|
|
8828b4fe52 | ||
|
|
87fdd203b5 | ||
|
|
187674ddac | ||
|
|
f94a08f12f | ||
|
|
252ad711f1 | ||
|
|
9d6bfd4786 | ||
|
|
d3690b12c6 | ||
|
|
32e08ca165 | ||
|
|
bc4f8fbe60 | ||
|
|
fd3deeb318 | ||
|
|
7108358ebd | ||
|
|
98daea0e97 | ||
|
|
48acb03b81 | ||
|
|
08ac485eac | ||
|
|
c033a81eca | ||
|
|
5df9127add | ||
|
|
b9e9cc534c | ||
|
|
79be464326 | ||
|
|
f67aad0b2d | ||
|
|
55b36fe719 | ||
|
|
7cce77cccd | ||
|
|
170f794c3a | ||
|
|
ae4bd79ca1 | ||
|
|
d76982bbeb | ||
|
|
fb4229c4ae | ||
|
|
caec338d25 | ||
|
|
b94200233d | ||
|
|
eb3ebe24e8 | ||
|
|
4514a4bfcc | ||
|
|
5e4e48fffe | ||
|
|
47a33f97f9 | ||
|
|
b36ef9da1e | ||
|
|
068861d0cc | ||
|
|
f2f8f3ccd2 | ||
|
|
2d7a1ce71a | ||
|
|
74d72eb257 | ||
|
|
9512ee657a | ||
|
|
78f80eb7dc | ||
|
|
fa525b4488 | ||
|
|
ee3e83e09c | ||
|
|
ea4354ba2e | ||
|
|
5c5c872afc | ||
|
|
9f2ffd102c | ||
|
|
34f8941868 | ||
|
|
07b217d9f8 | ||
|
|
cb83d319b9 | ||
|
|
23daa3efdf | ||
|
|
3a1ffceb58 | ||
|
|
f3431bd95d | ||
|
|
01c7250be2 | ||
|
|
e6bc36e110 | ||
|
|
afc1f5f4e1 | ||
|
|
4a2ad8b145 | ||
|
|
17ab0aba26 | ||
|
|
cc1b45b7cc | ||
|
|
4d990947de | ||
|
|
5542d6db21 | ||
|
|
8ca89ead0e | ||
|
|
ebf5f24487 | ||
|
|
90269d5204 | ||
|
|
e4332f6275 | ||
|
|
cd7168772d | ||
|
|
77ded80450 | ||
|
|
fbc69b6ae1 | ||
|
|
ea7dd699b9 | ||
|
|
018a852995 | ||
|
|
8a28ddbfe6 | ||
|
|
f186046c98 | ||
|
|
5644e834fa | ||
|
|
0b1f69bfd2 | ||
|
|
4eb5cd928e | ||
|
|
b8d47fe0a8 | ||
|
|
abcd9d77d4 | ||
|
|
095e5ede81 | ||
|
|
52754cbbbb | ||
|
|
ea9d048bc9 | ||
|
|
942224c685 | ||
|
|
670a25b039 | ||
|
|
cab02c86bc | ||
|
|
b4a67460e0 | ||
|
|
b56750df30 | ||
|
|
aa5fd64777 | ||
|
|
5a13b4df28 | ||
|
|
67bba95dd1 | ||
|
|
cd6152b193 | ||
|
|
67c070c20f | ||
|
|
2355bb8bb5 | ||
|
|
c4d24254db | ||
|
|
27b6bafd0f | ||
|
|
9cbdcc6260 | ||
|
|
192bbb715e | ||
|
|
014da3a225 | ||
|
|
803f4cd298 | ||
|
|
885a0508c0 | ||
|
|
a1472fb190 | ||
|
|
b86df7217c | ||
|
|
26815d042a | ||
|
|
026f21eddf | ||
|
|
30501aebb1 | ||
|
|
4014b1b574 | ||
|
|
8d54382b10 | ||
|
|
47dd8241b6 | ||
|
|
195da2adcc | ||
|
|
2b430eec6f | ||
|
|
d51e36998b | ||
|
|
a970a1263c | ||
|
|
cf9ccea70b | ||
|
|
f885cbb4ea | ||
|
|
97dfabc416 | ||
|
|
8d2b0749a0 | ||
|
|
a3acf4a8cc | ||
|
|
e505ab6019 | ||
|
|
9b24984b07 | ||
|
|
7ce08ea860 | ||
|
|
a156edbd73 | ||
|
|
9dae5827cc | ||
|
|
5da799244f | ||
|
|
bf79183bd6 | ||
|
|
afcb3b7ad8 | ||
|
|
5bfbcb210c | ||
|
|
4f65d45e55 | ||
|
|
3f8ecfedbb | ||
|
|
d8137a967c | ||
|
|
ffec935e2f | ||
|
|
253301ba4f | ||
|
|
69d2cfd56d | ||
|
|
0f90293252 | ||
|
|
0d166e1403 | ||
|
|
b5879e6e1d | ||
|
|
5b169b7f9d | ||
|
|
099a758c94 | ||
|
|
638e5d233a | ||
|
|
cacfdbad90 | ||
|
|
811bf6f449 | ||
|
|
43f8f3e4ad | ||
|
|
debe21de7b | ||
|
|
084066bde7 | ||
|
|
46d7dfc750 | ||
|
|
37c17e4300 | ||
|
|
d3aed076a6 | ||
|
|
c461624a67 | ||
|
|
e6060aff6b | ||
|
|
d1e6ee9cd7 | ||
|
|
6480a6e4e5 | ||
|
|
301a7c5dcd | ||
|
|
e70a0dcf3d | ||
|
|
d1ab3461a6 | ||
|
|
b81a6762bc | ||
|
|
04c418d02a | ||
|
|
27ea6ca092 | ||
|
|
cb94354099 | ||
|
|
53dab29ddb | ||
|
|
b1479e6e34 | ||
|
|
ea3262f7b0 | ||
|
|
143073b61d | ||
|
|
c472d60f80 | ||
|
|
0c01075ba8 | ||
|
|
1149d499a8 | ||
|
|
99d5266aa0 | ||
|
|
45c9d6185b | ||
|
|
e18a4afcbb | ||
|
|
499f86b065 | ||
|
|
1c4871acb3 | ||
|
|
3b683648fa | ||
|
|
3923f10277 | ||
|
|
1a681746b5 | ||
|
|
5703ef26cf | ||
|
|
5096d50d37 | ||
|
|
31debefbe1 | ||
|
|
c7d214e55a | ||
|
|
8cdd171ab7 | ||
|
|
9473c235f2 | ||
|
|
b443467770 | ||
|
|
a6bf9dd39c | ||
|
|
458b233e16 | ||
|
|
528f15f117 | ||
|
|
7c72aa8a80 | ||
|
|
2420c05930 | ||
|
|
3a312f3814 | ||
|
|
bac67bd91a | ||
|
|
36e67203a4 | ||
|
|
a52d1c97ec | ||
|
|
ac24d9be5b | ||
|
|
a0e800f102 | ||
|
|
7e4572a86a | ||
|
|
4f0d3a958d | ||
|
|
06c5ba7f0e |
No files matched your search
+2
-2
@@ -1,12 +1,12 @@
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-1
|
||||
image_family: freebsd-13-2
|
||||
|
||||
env:
|
||||
CCACHE_DIR: /tmp/ccache
|
||||
CIRRUS_CLONE_SUBMODULES: true
|
||||
|
||||
task:
|
||||
install_script: pkg install -y alsa-lib ccache cmake evdev-proto git libao libevdev libudev-devd libzip mesa-libs miniupnpc ninja pkgconf png pulseaudio sdl2
|
||||
install_script: pkg install -y alsa-lib ccache cmake evdev-proto git libao libevdev libudev-devd libzip mesa-libs miniupnpc ninja pkgconf pulseaudio sdl2
|
||||
ccache_cache:
|
||||
folder: /tmp/ccache
|
||||
script:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
custom: ['https://utip.io/flyinghead', 'https://www.paypal.com/paypalme/FlycastEmu']
|
||||
custom: ['https://www.paypal.com/paypalme/FlycastEmu']
|
||||
@@ -16,6 +16,12 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
@@ -23,14 +29,6 @@ jobs:
|
||||
key: android-ccache-${{ github.sha }}
|
||||
restore-keys: android-ccache-
|
||||
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: android-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: android-gradle-
|
||||
|
||||
- name: Gradle
|
||||
working-directory: shell/android-studio
|
||||
run: ./gradlew assembleRelease --parallel
|
||||
@@ -52,7 +50,7 @@ jobs:
|
||||
- name: Extract symbols
|
||||
run: |
|
||||
DUMP_SYMS=./core/deps/breakpad/bin/dump_syms
|
||||
SO_DIR=shell/android-studio/flycast/build/intermediates/cmake/release/obj
|
||||
SO_DIR=shell/android-studio/flycast/build/intermediates/merged_native_libs/release/out/lib
|
||||
for arch in arm64-v8a armeabi-v7a x86 x86_64 ; do
|
||||
$DUMP_SYMS $SO_DIR/$arch/libflycast.so > libflycast.so.sym
|
||||
BUILD_ID=`head -1 libflycast.so.sym | awk '{ print $4 }'`
|
||||
@@ -62,7 +60,7 @@ jobs:
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
id: aws-credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
with:
|
||||
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
|
||||
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
|
||||
@@ -74,7 +72,7 @@ jobs:
|
||||
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
|
||||
|
||||
- name: Setup Sentry CLI
|
||||
uses: mathieu-bour/setup-sentry-cli@1.2.0
|
||||
uses: mathieu-bour/setup-sentry-cli@v1
|
||||
env:
|
||||
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
|
||||
with:
|
||||
@@ -89,7 +87,7 @@ jobs:
|
||||
VERSION=$(git describe --tags --always)
|
||||
sentry-cli releases new "$VERSION"
|
||||
sentry-cli releases set-commits "$VERSION" --auto
|
||||
sentry-cli upload-dif symbols
|
||||
sentry-cli debug-files upload symbols
|
||||
shell: bash
|
||||
env:
|
||||
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
|
||||
|
||||
@@ -31,12 +31,12 @@ jobs:
|
||||
run: |
|
||||
# Unlink and re-link to prevent errors when github mac runner images install python outside of brew. See https://github.com/actions/setup-python/issues/577
|
||||
brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done
|
||||
brew update
|
||||
brew update || :
|
||||
brew install libao ldid ninja pulseaudio
|
||||
VULKAN_VER=1.3.224.1 && aria2c --parameterized-uri=true https://{sdk.lunarg.com/sdk/download/$VULKAN_VER/mac,distfiles.macports.org/MoltenVK}/vulkansdk-macos-$VULKAN_VER.dmg
|
||||
hdiutil attach ./vulkansdk-macos-*.dmg
|
||||
sudo /Volumes/vulkansdk-macos-*/InstallVulkan.app/Contents/MacOS/InstallVulkan --root $HOME/VulkanSDK --accept-licenses --default-answer --confirm-command install
|
||||
hdiutil detach /Volumes/vulkansdk-macos-*
|
||||
VULKAN_VER=1.3.261.1 && aria2c https://sdk.lunarg.com/sdk/download/$VULKAN_VER/mac/vulkansdk-macos-$VULKAN_VER.dmg
|
||||
hdiutil attach ./vulkansdk-macos-*.dmg -mountpoint /Volumes/VulkanSDK
|
||||
sudo /Volumes/VulkanSDK/InstallVulkan.app/Contents/MacOS/InstallVulkan --root $HOME/VulkanSDK --accept-licenses --default-answer --confirm-command install
|
||||
hdiutil detach /Volumes/VulkanSDK
|
||||
echo "VULKAN_SDK=$HOME/VulkanSDK/macOS" >> $GITHUB_ENV
|
||||
if: runner.os == 'macOS'
|
||||
|
||||
@@ -144,7 +144,7 @@ jobs:
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
id: aws-credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
with:
|
||||
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
|
||||
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
|
||||
@@ -157,7 +157,7 @@ jobs:
|
||||
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
|
||||
|
||||
- name: Setup Sentry CLI
|
||||
uses: mathieu-bour/setup-sentry-cli@1.2.0
|
||||
uses: mathieu-bour/setup-sentry-cli@v1
|
||||
env:
|
||||
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
|
||||
with:
|
||||
@@ -172,7 +172,7 @@ jobs:
|
||||
VERSION=$(git describe --tags --always)
|
||||
sentry-cli releases new "$VERSION"
|
||||
sentry-cli releases set-commits "$VERSION" --auto
|
||||
sentry-cli upload-dif symbols
|
||||
sentry-cli debug-files upload symbols
|
||||
shell: bash
|
||||
env:
|
||||
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
id: aws-credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
with:
|
||||
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
|
||||
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
|
||||
- name: CMake
|
||||
run: |
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.22000.0 -DCMAKE_SYSTEM_PROCESSOR=AMD64 -DCMAKE_CROSSCOMPILING=OFF -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%\scripts\buildsystems\vcpkg.cmake
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.22000.0 -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%\scripts\buildsystems\vcpkg.cmake
|
||||
cmake --build build --config Release --parallel 2
|
||||
shell: cmd
|
||||
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
id: aws-credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
with:
|
||||
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
|
||||
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
build/
|
||||
artifact/
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
@@ -6,8 +7,13 @@ shell/apple/emulator-ios/OpenMP/OpenMP.xcframework
|
||||
|
||||
# Visual Studio
|
||||
.vs/
|
||||
.vscode/
|
||||
out/
|
||||
|
||||
# JetBrains IDES
|
||||
.idea/
|
||||
cmake-build-*/
|
||||
|
||||
# Dependencies from .gitmodules
|
||||
core/deps/breakpad/
|
||||
core/deps/glslang/
|
||||
+25
-1
@@ -19,7 +19,7 @@
|
||||
.core-defs-osx-x64:
|
||||
extends: .core-defs
|
||||
variables:
|
||||
CORE_ARGS: -DLIBRETRO=ON -G Xcode -DCMAKE_BUILD_TYPE=Release
|
||||
CORE_ARGS: -DLIBRETRO=ON -G Xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64
|
||||
EXTRA_PATH: Release
|
||||
|
||||
.core-defs-osx-arm64:
|
||||
@@ -28,6 +28,11 @@
|
||||
CORE_ARGS: -DLIBRETRO=ON -G Xcode -DCMAKE_BUILD_TYPE=Release
|
||||
EXTRA_PATH: Release
|
||||
|
||||
.core-defs-ios-arm64:
|
||||
extends: .core-defs
|
||||
variables:
|
||||
CORE_ARGS: -DLIBRETRO=ON -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
.core-defs-android:
|
||||
extends: .core-defs
|
||||
script:
|
||||
@@ -62,11 +67,19 @@ include:
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/android-cmake.yml'
|
||||
|
||||
# iOS arm64
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ios-cmake.yml'
|
||||
|
||||
################################## CONSOLES ################################
|
||||
# Nintendo Switch
|
||||
# - project: 'libretro-infrastructure/ci-templates'
|
||||
# file: '/libnx-static.yml'
|
||||
|
||||
# tvOS arm64
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/tvos-cmake.yml'
|
||||
|
||||
# Stages for building
|
||||
stages:
|
||||
- build-prepare
|
||||
@@ -139,9 +152,20 @@ android-x86:
|
||||
- .libretro-android-cmake-x86
|
||||
- .core-defs-android
|
||||
|
||||
libretro-build-ios-arm64:
|
||||
extends:
|
||||
- .libretro-ios-cmake-arm64
|
||||
- .core-defs-ios-arm64
|
||||
|
||||
################################### CONSOLES #################################
|
||||
# Nintendo Switch
|
||||
#libretro-build-libnx-aarch64:
|
||||
# extends:
|
||||
# - .libretro-libnx-static-retroarch-master
|
||||
# - .core-defs
|
||||
|
||||
# tvOS arm64
|
||||
libretro-build-tvos-arm64:
|
||||
extends:
|
||||
- .libretro-tvos-cmake-arm64
|
||||
- .core-defs-ios-arm64
|
||||
+7
-1
@@ -3,7 +3,7 @@
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
[submodule "core/deps/libchdr"]
|
||||
path = core/deps/libchdr
|
||||
url = https://github.com/rtissera/libchdr.git
|
||||
url = https://github.com/flyinghead/libchdr.git
|
||||
[submodule "core/deps/luabridge"]
|
||||
path = core/deps/luabridge
|
||||
url = https://github.com/vinniefalco/LuaBridge.git
|
||||
@@ -22,3 +22,9 @@
|
||||
[submodule "core/deps/oboe"]
|
||||
path = core/deps/oboe
|
||||
url = https://github.com/google/oboe.git
|
||||
[submodule "core/deps/Syphon"]
|
||||
path = core/deps/Syphon
|
||||
url=https://github.com/vkedwardli/Syphon-Framework.git
|
||||
[submodule "core/deps/Spout"]
|
||||
path = core/deps/Spout
|
||||
url = https://github.com/vkedwardli/Spout2.git
|
||||
+224
-96
@@ -6,26 +6,6 @@ if(CCACHE_PROGRAM)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM} CACHE STRING "Compiler launcher for CXX.")
|
||||
endif()
|
||||
|
||||
option(ENABLE_CTEST "Enables unit tests" OFF)
|
||||
option(ENABLE_OPROFILE "Enable OProfile" OFF)
|
||||
option(TEST_AUTOMATION "Enable test automation" OFF)
|
||||
option(ENABLE_LOG "Enable full logging" OFF)
|
||||
option(ASAN "Enable address sanitizer" OFF)
|
||||
option(USE_GLES "Use GLES[3] API" OFF)
|
||||
option(USE_GLES2 "Use GLES2 API" OFF)
|
||||
option(USE_HOST_LIBZIP "Use host libzip" ON)
|
||||
option(USE_OPENMP "Use OpenMP if available" ON)
|
||||
option(USE_VULKAN "Build with Vulkan support" ON)
|
||||
option(USE_DX9 "Build with Direct3D 9 support" ON)
|
||||
option(USE_DX11 "Build with Direct3D 11 support" ON)
|
||||
option(LIBRETRO "Build libretro core" OFF)
|
||||
option(USE_OPENGL "Use OpenGL API" ON)
|
||||
option(USE_VIDEOCORE "RPI: use the legacy Broadcom GLES libraries" OFF)
|
||||
option(APPLE_BREAKPAD "macOS: Build breakpad client and dump symbols" OFF)
|
||||
option(ENABLE_GDB_SERVER "Build with GDB debugging support" OFF)
|
||||
option(ENABLE_DC_PROFILER "Build with support for target machine (SH4) profiler" OFF)
|
||||
option(ENABLE_FC_PROFILER "Build with support for host app (Flycast) profiler" OFF)
|
||||
|
||||
set(SENTRY_UPLOAD_URL "" CACHE STRING "Sentry upload URL")
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/shell/cmake")
|
||||
@@ -34,7 +14,9 @@ if(APPLE)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL iOS)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "Minimum iOS deployment version")
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "")
|
||||
set(USE_VULKAN OFF CACHE BOOL "Force vulkan off" FORCE)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL tvOS)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "Minimum tvOS deployment version")
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "")
|
||||
else()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum macOS deployment version")
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")
|
||||
@@ -47,7 +29,48 @@ else()
|
||||
project(flycast)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
include(DetectArchitecture)
|
||||
if(NOT DEFINED ARCHITECTURE)
|
||||
message(FATAL_ERROR "Unsupported architecture encountered. Ending CMake generation.")
|
||||
endif()
|
||||
message(STATUS "Target architecture: ${ARCHITECTURE}")
|
||||
|
||||
set(USE_HOST_SDL_DEFAULT OFF)
|
||||
if(NOT APPLE AND (NOT UNIX OR CMAKE_SYSTEM_NAME MATCHES "(FreeBSD|OpenBSD|NetBSD)"))
|
||||
set(USE_HOST_SDL_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
option(ENABLE_CTEST "Enables unit tests" OFF)
|
||||
option(ENABLE_OPROFILE "Enable OProfile" OFF)
|
||||
option(TEST_AUTOMATION "Enable test automation" OFF)
|
||||
option(ENABLE_LOG "Enable full logging" OFF)
|
||||
option(ASAN "Enable address sanitizer" OFF)
|
||||
option(USE_GLES "Use GLES[3] API" OFF)
|
||||
option(USE_GLES2 "Use GLES2 API" OFF)
|
||||
option(USE_HOST_LIBZIP "Use host libzip" ON)
|
||||
option(USE_HOST_SDL "Use host SDL library" ${USE_HOST_SDL_DEFAULT})
|
||||
option(USE_OPENMP "Use OpenMP if available" ON)
|
||||
option(USE_VULKAN "Build with Vulkan support" ON)
|
||||
option(USE_DX9 "Build with Direct3D 9 support" ON)
|
||||
option(USE_DX11 "Build with Direct3D 11 support" ON)
|
||||
option(LIBRETRO "Build libretro core" OFF)
|
||||
option(USE_OPENGL "Use OpenGL API" ON)
|
||||
option(USE_VIDEOCORE "RPI: use the legacy Broadcom GLES libraries" OFF)
|
||||
option(APPLE_BREAKPAD "macOS: Build breakpad client and dump symbols" OFF)
|
||||
option(ENABLE_GDB_SERVER "Build with GDB debugging support" OFF)
|
||||
option(ENABLE_DC_PROFILER "Build with support for target machine (SH4) profiler" OFF)
|
||||
option(ENABLE_FC_PROFILER "Build with support for host app (Flycast) profiler" OFF)
|
||||
|
||||
if(IOS AND NOT LIBRETRO)
|
||||
set(USE_VULKAN OFF CACHE BOOL "Force vulkan off" FORCE)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakeRC)
|
||||
|
||||
if(ENABLE_CTEST)
|
||||
include(CTest)
|
||||
@@ -73,7 +96,7 @@ if(GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(WINDOWS_STORE)
|
||||
string(REPLACE "v" "" MS_VERSION ${GIT_VERSION})
|
||||
string(REGEX REPLACE "[Vv]" "" MS_VERSION ${GIT_VERSION})
|
||||
string(REPLACE "-" "." MS_VERSION ${MS_VERSION})
|
||||
string(REGEX REPLACE "\.g[0-9a-f]+" "" MS_VERSION ${MS_VERSION})
|
||||
string(REGEX MATCH "[0-9]+\.[0-9]+\.[0-9]+" VERSION_3PARTS ${MS_VERSION})
|
||||
@@ -108,18 +131,33 @@ if(NINTENDO_SWITCH)
|
||||
elseif(LIBRETRO)
|
||||
add_library(${PROJECT_NAME} SHARED core/emulator.cpp)
|
||||
if(APPLE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,error")
|
||||
if(NOT IOS)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,error")
|
||||
endif()
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/shell/libretro/libretro.osx.def")
|
||||
else()
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
|
||||
endif()
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "flycast_libretro")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "flycast_libretro"
|
||||
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
|
||||
)
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE LIBRETRO)
|
||||
if(APPLE)
|
||||
find_library(FOUNDATION Foundation)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${FOUNDATION})
|
||||
endif()
|
||||
if(ANDROID OR USE_GLES)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE GLES GLES3 HAVE_OPENGLES HAVE_OPENGLES3)
|
||||
find_library(GLES3_LIBRARIES NAMES GLESv3 GLESv2 NO_CACHE REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${GLES3_LIBRARIES})
|
||||
elseif(IOS)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE GLES GLES3 HAVE_OPENGLES HAVE_OPENGLES3)
|
||||
find_library(OPENGLES OpenGLES)
|
||||
find_library(GLKIT GLKit)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${OPENGLES} ${GLKIT})
|
||||
elseif(USE_GLES2)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE GLES GLES2 HAVE_OPENGLES HAVE_OPENGLES2)
|
||||
if(USE_VIDEOCORE)
|
||||
@@ -160,10 +198,8 @@ endif()
|
||||
if(WINDOWS_STORE)
|
||||
set(USE_OPENGL OFF)
|
||||
set(USE_VULKAN OFF)
|
||||
target_compile_features(${PROJECT_NAME} PRIVATE c_std_11 cxx_std_17)
|
||||
else()
|
||||
target_compile_features(${PROJECT_NAME} PRIVATE c_std_11 cxx_std_11)
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
CXX_EXTENSIONS OFF
|
||||
LINK_FLAGS_RELEASE -s)
|
||||
@@ -178,27 +214,32 @@ else()
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wall>)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
$<$<BOOL:APPLE>:GL_SILENCE_DEPRECATION>
|
||||
$<$<BOOL:MSVC>:_CRT_NONSTDC_NO_WARNINGS>
|
||||
$<$<BOOL:MSVC>:_CRT_SECURE_NO_WARNINGS>
|
||||
$<$<BOOL:MSVC>:_USE_MATH_DEFINES>
|
||||
$<$<BOOL:MSVC>:NOMINMAX>
|
||||
$<$<BOOL:${TEST_AUTOMATION}>:TEST_AUTOMATION>
|
||||
$<$<BOOL:${ENABLE_LOG}>:DEBUGFAST>)
|
||||
if(IOS)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
TARGET_IPHONE
|
||||
GLES
|
||||
GLES3
|
||||
GLES_SILENCE_DEPRECATION)
|
||||
if(${CMAKE_OSX_SYSROOT} MATCHES "\/MacOSX.platform\/Developer\/SDKs")
|
||||
set(TARGET_MAC ON)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
$<$<BOOL:${APPLE}>:GL_SILENCE_DEPRECATION>
|
||||
$<$<BOOL:${ENABLE_LOG}>:DEBUGFAST>
|
||||
$<$<BOOL:${IOS}>:TARGET_IPHONE>
|
||||
$<$<BOOL:${TARGET_MAC}>:TARGET_MAC>
|
||||
$<$<BOOL:${IOS}>:GLES>
|
||||
$<$<BOOL:${IOS}>:GLES3>
|
||||
$<$<BOOL:${IOS}>:GLES_SILENCE_DEPRECATION>
|
||||
$<$<BOOL:${MSVC}>:_CRT_NONSTDC_NO_WARNINGS>
|
||||
$<$<BOOL:${MSVC}>:_CRT_SECURE_NO_WARNINGS>
|
||||
$<$<BOOL:${MSVC}>:_WINSOCK_DEPRECATED_NO_WARNING>
|
||||
$<$<BOOL:${MSVC}>:NOMINMAX>
|
||||
$<$<BOOL:${NINTENDO_SWITCH}>:_DEFAULT_SOURCE>
|
||||
$<$<BOOL:${TEST_AUTOMATION}>:TEST_AUTOMATION>
|
||||
$<$<BOOL:${WINDOWS_STORE}>:NOCRYPT>
|
||||
$<$<OR:$<BOOL:${MINGW}>,$<BOOL:${MSVC}>>:_USE_MATH_DEFINES>)
|
||||
|
||||
if(NOT "${SENTRY_UPLOAD_URL}" STREQUAL "")
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE SENTRY_UPLOAD="${SENTRY_UPLOAD_URL}")
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core core/deps core/deps/stb core/khronos core/deps/json)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core core/deps core/deps/stb core/deps/khronos core/deps/json)
|
||||
if(LIBRETRO)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE shell/libretro)
|
||||
endif()
|
||||
@@ -336,11 +377,11 @@ if(USE_VULKAN)
|
||||
option(BUILD_EXTERNAL "Build external dependencies in /External" OFF)
|
||||
option(SKIP_GLSLANG_INSTALL "Skip installation" ON)
|
||||
option(ENABLE_SPVREMAPPER "Enables building of SPVRemapper" OFF)
|
||||
option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" OFF)
|
||||
option(ENABLE_GLSLANG_BINARIES "Builds glslang and spirv-remap" OFF)
|
||||
option(ENABLE_HLSL "Enables HLSL input support" OFF)
|
||||
option(ENABLE_PCH "Enables Precompiled header" OFF)
|
||||
add_subdirectory(core/deps/glslang EXCLUDE_FROM_ALL)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE SPIRV)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE glslang-default-resource-limits SPIRV)
|
||||
endif()
|
||||
|
||||
if(NOT LIBRETRO)
|
||||
@@ -356,7 +397,7 @@ if(NOT LIBRETRO)
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID AND NOT IOS)
|
||||
if(NOT APPLE AND (NOT UNIX OR CMAKE_SYSTEM_NAME MATCHES "(FreeBSD|OpenBSD|NetBSD)"))
|
||||
if(USE_HOST_SDL)
|
||||
find_package(SDL2)
|
||||
endif()
|
||||
if(NOT SDL2_FOUND)
|
||||
@@ -394,7 +435,7 @@ if(NOT LIBRETRO)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB)
|
||||
endif()
|
||||
|
||||
find_package(Lua)
|
||||
find_package(Lua 5.2)
|
||||
if(NOT APPLE AND LUA_FOUND)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LUA)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${LUA_INCLUDE_DIR} core/deps/luabridge/Source)
|
||||
@@ -498,7 +539,7 @@ if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*" AND NOT LIBRETRO)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND "x86_64" IN_LIST ARCHITECTURE AND NOT LIBRETRO)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE False)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.14.0")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
|
||||
@@ -534,6 +575,13 @@ if(ASAN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID AND "arm" IN_LIST ARCHITECTURE)
|
||||
enable_language(ASM)
|
||||
option(LIBUNWIND_ENABLE_SHARED "Build libunwind as a shared library." OFF)
|
||||
add_subdirectory(core/deps/libunwind/libunwind)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE unwind_static)
|
||||
endif()
|
||||
|
||||
if(ANDROID AND NOT LIBRETRO)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
add_subdirectory(core/deps/oboe)
|
||||
@@ -545,7 +593,9 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/deps/chdpsr/cdipsr.cpp
|
||||
core/deps/chdpsr/cdipsr.h)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/nowide/include)
|
||||
add_subdirectory(core/deps/nowide EXCLUDE_FROM_ALL)
|
||||
target_compile_definitions(nowide PRIVATE $<$<BOOL:${NINTENDO_SWITCH}>:_DEFAULT_SOURCE>)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE nowide::nowide)
|
||||
|
||||
if(NOT MINIUPNP_FOUND)
|
||||
if(NINTENDO_SWITCH)
|
||||
@@ -651,12 +701,15 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE _7ZIP_ST)
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/deps/lzma/7zArcIn.c core/deps/lzma/7zBuf.c core/deps/lzma/7zCrc.c core/deps/lzma/7zCrcOpt.c core/deps/lzma/7zDec.c core/deps/lzma/7zFile.c core/deps/lzma/7zStream.c core/deps/lzma/Alloc.c core/deps/lzma/Bcj2.c core/deps/lzma/Bra86.c core/deps/lzma/Bra.c core/deps/lzma/BraIA64.c core/deps/lzma/CpuArch.c core/deps/lzma/Delta.c core/deps/lzma/LzFind.c core/deps/lzma/Lzma2Dec.c core/deps/lzma/Lzma86Dec.c core/deps/lzma/Lzma86Enc.c core/deps/lzma/LzmaDec.c core/deps/lzma/LzmaEnc.c core/deps/lzma/LzmaLib.c core/deps/lzma/Sort.c)
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/deps/libelf/elf32.cpp core/deps/libelf/elf64.cpp core/deps/libelf/elf.cpp)
|
||||
add_subdirectory(core/deps/libelf)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE elf)
|
||||
if(NOT LIBRETRO)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE IMGUI_DISABLE_DEMO_WINDOWS)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/deps/imgui/imgui.cpp
|
||||
core/deps/imgui/imgui_demo.cpp
|
||||
core/deps/imgui/imgui_draw.cpp
|
||||
core/deps/imgui/imgui_tables.cpp
|
||||
core/deps/imgui/imgui_widgets.cpp)
|
||||
|
||||
if(ENABLE_FC_PROFILER)
|
||||
@@ -670,6 +723,9 @@ endif()
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/deps/xbrz/xbrz.cpp)
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/deps/md5/md5.cpp)
|
||||
|
||||
cmrc_add_resource_library(flycast-resources ALIAS flycast::res NAMESPACE flycast)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE flycast::res)
|
||||
|
||||
if(LIBRETRO)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/libretro-common/include)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
@@ -686,7 +742,7 @@ if(LIBRETRO)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/deps/libretro-common/glsm/glsm.c
|
||||
core/deps/libretro-common/glsym/rglgen.c)
|
||||
if(ANDROID OR USE_GLES)
|
||||
if(ANDROID OR IOS OR USE_GLES)
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/deps/libretro-common/glsym/glsym_es3.c)
|
||||
elseif(USE_GLES2)
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/deps/libretro-common/glsym/glsym_es2.c)
|
||||
@@ -706,6 +762,9 @@ if(LIBRETRO)
|
||||
shell/libretro/option.cpp
|
||||
shell/libretro/oslib.cpp
|
||||
shell/libretro/vmu_xhair.cpp)
|
||||
if(APPLE)
|
||||
target_sources(${PROJECT_NAME} PRIVATE shell/libretro/oslib_apple.mm)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
@@ -760,8 +819,14 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/hw/bba/bba.cpp
|
||||
core/hw/bba/rtl8139c.h
|
||||
core/hw/bba/rtl8139c.cpp
|
||||
core/hw/flashrom/at93cxx.cpp
|
||||
core/hw/flashrom/at93cxx.h
|
||||
core/hw/flashrom/flashrom.cpp
|
||||
core/hw/flashrom/flashrom.h
|
||||
core/hw/flashrom/nvmem.cpp
|
||||
core/hw/flashrom/nvmem.h
|
||||
core/hw/flashrom/x76f100.cpp
|
||||
core/hw/flashrom/x76f100.h
|
||||
core/hw/gdrom/gdrom_if.h
|
||||
core/hw/gdrom/gdrom_response.cpp
|
||||
core/hw/gdrom/gdromv3.cpp
|
||||
@@ -781,8 +846,8 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/hw/maple/maple_if.cpp
|
||||
core/hw/maple/maple_if.h
|
||||
core/hw/maple/maple_jvs.cpp
|
||||
core/hw/mem/_vmem.cpp
|
||||
core/hw/mem/_vmem.h
|
||||
core/hw/mem/addrspace.cpp
|
||||
core/hw/mem/addrspace.h
|
||||
core/hw/mem/mem_watch.cpp
|
||||
core/hw/mem/mem_watch.h
|
||||
core/hw/modem/modem.cpp
|
||||
@@ -799,6 +864,8 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/hw/naomi/m1cartridge.h
|
||||
core/hw/naomi/m4cartridge.cpp
|
||||
core/hw/naomi/m4cartridge.h
|
||||
core/hw/naomi/multiboard.h
|
||||
core/hw/naomi/multiboard.cpp
|
||||
core/hw/naomi/naomi_cart.cpp
|
||||
core/hw/naomi/naomi_cart.h
|
||||
core/hw/naomi/naomi_flashrom.cpp
|
||||
@@ -811,12 +878,21 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/hw/naomi/naomi_roms.cpp
|
||||
core/hw/naomi/naomi_roms.h
|
||||
core/hw/naomi/naomi_roms_input.h
|
||||
core/hw/naomi/netdimm.cpp
|
||||
core/hw/naomi/netdimm.h
|
||||
core/hw/naomi/card_reader.h
|
||||
core/hw/naomi/card_reader.cpp
|
||||
core/hw/naomi/touchscreen.h
|
||||
core/hw/naomi/touchscreen.cpp
|
||||
core/hw/naomi/printer.h
|
||||
core/hw/naomi/printer.cpp
|
||||
core/hw/naomi/systemsp.h
|
||||
core/hw/naomi/systemsp.cpp
|
||||
core/hw/naomi/hopper.h
|
||||
core/hw/naomi/hopper.cpp
|
||||
core/hw/pvr/elan.cpp
|
||||
core/hw/pvr/elan.h
|
||||
core/hw/pvr/elan_struct.h
|
||||
core/hw/pvr/helper_classes.h
|
||||
core/hw/pvr/pvr.cpp
|
||||
core/hw/pvr/pvr.h
|
||||
core/hw/pvr/pvr_mem.cpp
|
||||
@@ -872,6 +948,8 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/hw/sh4/modules/ubc.cpp
|
||||
core/hw/sh4/modules/wince.h
|
||||
core/hw/sh4/sh4_cache.h
|
||||
core/hw/sh4/sh4_cycles.cpp
|
||||
core/hw/sh4/sh4_cycles.h
|
||||
core/hw/sh4/sh4_core.h
|
||||
core/hw/sh4/sh4_core_regs.cpp
|
||||
core/hw/sh4/sh4_if.h
|
||||
@@ -887,7 +965,32 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/hw/sh4/sh4_rom.cpp
|
||||
core/hw/sh4/sh4_rom.h
|
||||
core/hw/sh4/sh4_sched.cpp
|
||||
core/hw/sh4/sh4_sched.h)
|
||||
core/hw/sh4/sh4_sched.h
|
||||
core/hw/sh4/storeq.cpp)
|
||||
|
||||
cmrc_add_resources(flycast-resources
|
||||
WHENCE resources
|
||||
resources/flash/alienfnt.nvmem.zip # network settings
|
||||
resources/flash/gunsur2.nvmem.zip
|
||||
resources/flash/mazan.nvmem.zip # free play, calibrated
|
||||
resources/flash/otrigger.nvmem.zip
|
||||
resources/flash/wldkicks.nvmem.zip # free play
|
||||
resources/flash/wldkicksj.nvmem.zip # free play
|
||||
resources/flash/wldkicksu.nvmem.zip # free play
|
||||
resources/flash/f355.nvmem.zip # printer on
|
||||
resources/flash/f355twin.nvmem.zip
|
||||
resources/flash/f355twn2.nvmem.zip
|
||||
resources/flash/dirtypig.nvmem.zip # 4 players
|
||||
resources/flash/dirtypig.nvmem2.zip
|
||||
resources/flash/vf4.nvmem.zip # card all day, stage select
|
||||
resources/flash/vf4evob.nvmem.zip # card all day, stage select
|
||||
resources/flash/vf4tuned.nvmem.zip) # card all day, stage select, 45 sec time limit, 3 match
|
||||
|
||||
cmrc_add_resources(flycast-resources
|
||||
fonts/printer_ascii8x16.bin
|
||||
fonts/printer_ascii12x24.bin
|
||||
fonts/printer_kanji16x16.bin
|
||||
fonts/printer_kanji24x24.bin)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/imgread/cdi.cpp
|
||||
@@ -961,6 +1064,8 @@ if(NOT LIBRETRO)
|
||||
endif()
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/network/alienfnt_modem.cpp
|
||||
core/network/alienfnt_modem.h
|
||||
core/network/dns.cpp
|
||||
core/network/ggpo.cpp
|
||||
core/network/ggpo.h
|
||||
@@ -1002,6 +1107,10 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/oslib/directory.h
|
||||
core/oslib/host_context.h
|
||||
core/oslib/oslib.h
|
||||
core/oslib/storage.cpp
|
||||
core/oslib/storage.h
|
||||
core/oslib/unwind_info.h
|
||||
core/oslib/virtmem.h
|
||||
core/lua/lua.cpp
|
||||
core/lua/lua.h)
|
||||
|
||||
@@ -1021,19 +1130,16 @@ if (ENABLE_FC_PROFILER)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE FC_PROFILER)
|
||||
endif()
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/rec-cpp/rec_cpp.cpp)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/reios/descrambl.cpp
|
||||
core/reios/descrambl.h
|
||||
core/reios/font.h
|
||||
core/reios/gdrom_hle.cpp
|
||||
core/reios/gdrom_hle.h
|
||||
core/reios/reios.cpp
|
||||
core/reios/reios.h
|
||||
core/reios/reios_elf.cpp
|
||||
core/reios/reios_elf.h)
|
||||
cmrc_add_resources(flycast-resources fonts/biosfont.bin)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/wsi/context.h
|
||||
@@ -1080,8 +1186,8 @@ if(USE_OPENGL)
|
||||
|
||||
if(NOT LIBRETRO)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/rend/gles/imgui_impl_opengl3.cpp
|
||||
core/rend/gles/imgui_impl_opengl3.h
|
||||
core/deps/imgui/backends/imgui_impl_opengl3.cpp
|
||||
core/deps/imgui/backends/imgui_impl_opengl3.h
|
||||
core/rend/gles/opengl_driver.cpp
|
||||
core/rend/gles/opengl_driver.h)
|
||||
endif()
|
||||
@@ -1155,15 +1261,16 @@ if(USE_VULKAN)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_WIN32_KHR)
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_MACOS_MVK)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_METAL_EXT)
|
||||
endif()
|
||||
|
||||
add_subdirectory(core/deps/Vulkan-Headers)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Headers)
|
||||
|
||||
add_library(VulkanMemoryAllocator INTERFACE)
|
||||
add_subdirectory(core/deps/VulkanMemoryAllocator)
|
||||
target_compile_definitions(VulkanMemoryAllocator INTERFACE $<$<BOOL:${APPLE}>:VMA_USE_STL_SHARED_MUTEX=0>) # Only available on macOS 10.12+
|
||||
target_compile_options(VulkanMemoryAllocator INTERFACE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:AppleClang,Clang>>:-Wno-nullability-completeness>)
|
||||
target_include_directories(VulkanMemoryAllocator INTERFACE core/deps/VulkanMemoryAllocator/include)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE VulkanMemoryAllocator)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE GPUOpen::VulkanMemoryAllocator)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_VULKAN HAVE_VULKAN)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
@@ -1179,6 +1286,7 @@ if(USE_VULKAN)
|
||||
core/rend/vulkan/oit/oit_shaders.h
|
||||
core/rend/vulkan/buffer.cpp
|
||||
core/rend/vulkan/buffer.h
|
||||
core/rend/vulkan/commandpool.cpp
|
||||
core/rend/vulkan/commandpool.h
|
||||
core/rend/vulkan/compiler.cpp
|
||||
core/rend/vulkan/compiler.h
|
||||
@@ -1209,15 +1317,15 @@ if(USE_VULKAN)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/rend/vulkan/vulkan_driver.h
|
||||
core/rend/vulkan/vulkan_context.cpp
|
||||
core/rend/vulkan/imgui_impl_vulkan.cpp
|
||||
core/rend/vulkan/imgui_impl_vulkan.h)
|
||||
core/deps/imgui/backends/imgui_impl_vulkan.cpp
|
||||
core/deps/imgui/backends/imgui_impl_vulkan.h)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE ImTextureID=ImU64)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32 AND USE_DX9 AND NOT LIBRETRO AND NOT WINDOWS_STORE)
|
||||
if(WIN32 AND USE_DX9 AND NOT LIBRETRO AND NOT WINDOWS_STORE AND ("x86" IN_LIST ARCHITECTURE OR "x86_64" IN_LIST ARCHITECTURE))
|
||||
set(REND_DX9_FILES
|
||||
core/rend/dx9/d3d_overlay.h
|
||||
core/rend/dx9/d3d_overlay.cpp
|
||||
@@ -1230,8 +1338,8 @@ if(WIN32 AND USE_DX9 AND NOT LIBRETRO AND NOT WINDOWS_STORE)
|
||||
core/rend/dx9/dx9_driver.h
|
||||
core/rend/dx9/dxcontext.cpp
|
||||
core/rend/dx9/dxcontext.h
|
||||
core/rend/dx9/imgui_impl_dx9.h
|
||||
core/rend/dx9/imgui_impl_dx9.cpp)
|
||||
core/deps/imgui/backends/imgui_impl_dx9.h
|
||||
core/deps/imgui/backends/imgui_impl_dx9.cpp)
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${REND_DX9_FILES})
|
||||
|
||||
if(NOT MINGW)
|
||||
@@ -1250,8 +1358,8 @@ endif()
|
||||
if(WIN32 AND USE_DX11)
|
||||
if(NOT LIBRETRO)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/rend/dx11/imgui_impl_dx11.cpp
|
||||
core/rend/dx11/imgui_impl_dx11.h)
|
||||
core/deps/imgui/backends/imgui_impl_dx11.cpp
|
||||
core/deps/imgui/backends/imgui_impl_dx11.h)
|
||||
endif()
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/rend/dx11/dx11_driver.h
|
||||
@@ -1278,7 +1386,7 @@ if(WIN32 AND USE_DX11)
|
||||
core/rend/dx11/oit/dx11_oitshaders.h)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE HAVE_D3D11)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE d3d11 d3dcompiler)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE d3d11 d3dcompiler dxgi)
|
||||
endif()
|
||||
|
||||
if(ENABLE_GDB_SERVER)
|
||||
@@ -1289,7 +1397,10 @@ if(ENABLE_GDB_SERVER)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE GDB_SERVER)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)" AND NOT APPLE)
|
||||
if("arm" IN_LIST ARCHITECTURE AND NOT APPLE)
|
||||
if(MSVC)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE "/Zc:__cplusplus")
|
||||
endif()
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/vixl)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/rec-ARM/rec_arm.cpp
|
||||
@@ -1305,8 +1416,6 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)" AND NOT APPLE)
|
||||
core/deps/vixl/aarch32/macro-assembler-aarch32.h
|
||||
core/deps/vixl/aarch32/operands-aarch32.cc
|
||||
core/deps/vixl/aarch32/operands-aarch32.h
|
||||
core/deps/vixl/aarch32/disasm-aarch32.cc
|
||||
core/deps/vixl/aarch32/disasm-aarch32.h
|
||||
core/deps/vixl/assembler-base-vixl.h
|
||||
core/deps/vixl/code-buffer-vixl.cc
|
||||
core/deps/vixl/code-buffer-vixl.h
|
||||
@@ -1323,35 +1432,28 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)" AND NOT APPLE)
|
||||
core/deps/vixl/pool-manager-impl.h
|
||||
core/deps/vixl/utils-vixl.cc
|
||||
core/deps/vixl/utils-vixl.h)
|
||||
set(KNOWN_ARCHITECTURE_DETECTED ON)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*|arm64.*)" OR CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
|
||||
if("arm64" IN_LIST ARCHITECTURE)
|
||||
if(MSVC)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE "/Zc:__cplusplus")
|
||||
endif()
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/vixl)
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/deps/vixl/aarch64/abi-aarch64.h
|
||||
core/deps/vixl/aarch64/assembler-aarch64.cc
|
||||
core/deps/vixl/aarch64/assembler-aarch64.h
|
||||
core/deps/vixl/aarch64/assembler-sve-aarch64.cc
|
||||
core/deps/vixl/aarch64/constants-aarch64.h
|
||||
core/deps/vixl/aarch64/cpu-aarch64.cc
|
||||
core/deps/vixl/aarch64/cpu-aarch64.h
|
||||
core/deps/vixl/aarch64/cpu-features-auditor-aarch64.cc
|
||||
core/deps/vixl/aarch64/cpu-features-auditor-aarch64.h
|
||||
core/deps/vixl/aarch64/decoder-aarch64.cc
|
||||
core/deps/vixl/aarch64/decoder-aarch64.h
|
||||
core/deps/vixl/aarch64/disasm-aarch64.cc
|
||||
core/deps/vixl/aarch64/disasm-aarch64.h
|
||||
core/deps/vixl/aarch64/instructions-aarch64.cc
|
||||
core/deps/vixl/aarch64/instructions-aarch64.h
|
||||
core/deps/vixl/aarch64/instrument-aarch64.cc
|
||||
core/deps/vixl/aarch64/instrument-aarch64.h
|
||||
core/deps/vixl/aarch64/logic-aarch64.cc
|
||||
core/deps/vixl/aarch64/macro-assembler-aarch64.cc
|
||||
core/deps/vixl/aarch64/macro-assembler-aarch64.h
|
||||
core/deps/vixl/aarch64/macro-assembler-sve-aarch64.cc
|
||||
core/deps/vixl/aarch64/operands-aarch64.cc
|
||||
core/deps/vixl/aarch64/operands-aarch64.h
|
||||
core/deps/vixl/aarch64/registers-aarch64.cc
|
||||
core/deps/vixl/aarch64/registers-aarch64.h
|
||||
core/deps/vixl/aarch64/pointer-auth-aarch64.cc
|
||||
core/deps/vixl/aarch64/simulator-aarch64.cc
|
||||
core/deps/vixl/aarch64/simulator-aarch64.h
|
||||
core/deps/vixl/aarch64/simulator-constants-aarch64.h
|
||||
core/deps/vixl/assembler-base-vixl.h
|
||||
core/deps/vixl/code-buffer-vixl.cc
|
||||
@@ -1370,9 +1472,8 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*|arm64.*)" OR CMAKE_OSX_
|
||||
core/deps/vixl/utils-vixl.cc
|
||||
core/deps/vixl/utils-vixl.h)
|
||||
target_sources(${PROJECT_NAME} PRIVATE core/rec-ARM64/rec_arm64.cpp core/rec-ARM64/arm64_regalloc.h)
|
||||
set(KNOWN_ARCHITECTURE_DETECTED ON)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|x86_64.*|AMD64.*" OR CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
|
||||
if("x86" IN_LIST ARCHITECTURE OR "x86_64" IN_LIST ARCHITECTURE)
|
||||
add_subdirectory(core/deps/xbyak EXCLUDE_FROM_ALL)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE xbyak::xbyak)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
@@ -1388,10 +1489,6 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|x86_64.*|AMD64.*"
|
||||
core/rec-x64/rec_x64.cpp
|
||||
core/rec-x64/x64_regalloc.h)
|
||||
endif()
|
||||
set(KNOWN_ARCHITECTURE_DETECTED ON)
|
||||
endif()
|
||||
if(NOT KNOWN_ARCHITECTURE_DETECTED)
|
||||
message(FATAL_ERROR "Unknown target processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
if(NOT LIBRETRO)
|
||||
@@ -1532,6 +1629,20 @@ if(NOT LIBRETRO)
|
||||
COMMAND ldid -S${CMAKE_CURRENT_SOURCE_DIR}/shell/apple/emulator-ios/emulator/flycast.entitlements ${CMAKE_CURRENT_BINARY_DIR}/Payload/Flycast.app/Flycast
|
||||
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>-${CMAKE_OSX_SYSROOT}/Flycast.ipa" --format=zip ${CMAKE_CURRENT_BINARY_DIR}/Payload)
|
||||
else()
|
||||
|
||||
add_subdirectory(core/deps/Syphon)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Syphon)
|
||||
if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${SYPHON_METALLIB}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/Resources/)
|
||||
else()
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${SYPHON_METALLIB}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/Resources/)
|
||||
endif()
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE VIDEO_ROUTING)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
shell/apple/common/http_client.mm
|
||||
shell/apple/emulator-osx/emulator-osx/SDLMain.h
|
||||
@@ -1568,6 +1679,7 @@ if(NOT LIBRETRO)
|
||||
find_library(FOUNDATION_LIBRARY Foundation)
|
||||
find_library(AUDIO_TOOLBOX_LIBRARY AudioToolbox)
|
||||
find_library(OPENGL_LIBRARY OpenGL)
|
||||
find_library(METAL_LIBRARY Metal)
|
||||
find_library(IOSURFACE_LIBRARY IOSurface)
|
||||
find_library(MULTITOUCH_SUPPORT_LIBRARY MultitouchSupport /System/Library/PrivateFrameworks)
|
||||
|
||||
@@ -1576,6 +1688,7 @@ if(NOT LIBRETRO)
|
||||
${FOUNDATION_LIBRARY}
|
||||
${AUDIO_TOOLBOX_LIBRARY}
|
||||
${OPENGL_LIBRARY}
|
||||
${METAL_LIBRARY}
|
||||
${IOSURFACE_LIBRARY}
|
||||
${MULTITOUCH_SUPPORT_LIBRARY})
|
||||
|
||||
@@ -1622,6 +1735,18 @@ if(NOT LIBRETRO)
|
||||
shell/uwp/http_client.cpp)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES RESOURCE "${ResourceFiles}")
|
||||
else()
|
||||
if("x86" IN_LIST ARCHITECTURE OR "x86_64" IN_LIST ARCHITECTURE)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/Spout/SPOUTSDK/SpoutGL)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/Spout/SPOUTSDK/SpoutDirectX/SpoutDX)
|
||||
SET(SPOUT_BUILD_CMT OFF CACHE BOOL "For Visual Studio - build /MT to link runtime libraries" FORCE)
|
||||
SET(SPOUT_BUILD_SPOUTDX ON CACHE BOOL "Build SpoutDX DirectX11 support library" FORCE)
|
||||
SET(SPOUT_BUILD_LIBRARY OFF CACHE BOOL "Build C-compatible cross compiler library" FORCE)
|
||||
SET(SKIP_INSTALL_ALL ON CACHE BOOL "Install headers and libraries" FORCE)
|
||||
add_subdirectory(core/deps/Spout)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Spout_static SpoutDX_static)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE VIDEO_ROUTING)
|
||||
endif()
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE shell/windows/flycast.rc)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE dsound opengl32 winmm ws2_32 wsock32 xinput9_1_0 cfgmgr32 wininet)
|
||||
endif()
|
||||
@@ -1640,7 +1765,8 @@ if(BUILD_TESTING)
|
||||
tests/src/test_stubs.cpp
|
||||
tests/src/serialize_test.cpp
|
||||
tests/src/AicaArmTest.cpp
|
||||
tests/src/Sh4InterpreterTest.cpp)
|
||||
tests/src/Sh4InterpreterTest.cpp
|
||||
tests/src/MmuTest.cpp)
|
||||
endif()
|
||||
|
||||
if(NINTENDO_SWITCH)
|
||||
@@ -1649,6 +1775,8 @@ if(NINTENDO_SWITCH)
|
||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:xxHash::xxhash>
|
||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:chdr-static>
|
||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:zip>
|
||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:elf>
|
||||
COMMAND ${CMAKE_AR} -x $<TARGET_FILE:flycast::res>
|
||||
COMMAND ${CMAKE_AR} -rs flycast_libretro_libnx.a *.obj
|
||||
COMMAND rm *.obj
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
|
||||
|
||||
@@ -15,7 +15,7 @@ Join us on our [**Discord server**](https://discord.gg/X8YWP8w) for a chat.
|
||||
|
||||
## Install
|
||||
|
||||
### Flatpak (Linux)
|
||||
### Flatpak (Linux )
|
||||
|
||||
1. [Set up Flatpak](https://www.flatpak.org/setup/).
|
||||
|
||||
@@ -27,7 +27,7 @@ Join us on our [**Discord server**](https://discord.gg/X8YWP8w) for a chat.
|
||||
|
||||
`flatpak run org.flycast.Flycast`
|
||||
|
||||
### Homebrew (MacOS)
|
||||
### Homebrew (MacOS )
|
||||
|
||||
1. [Set up Homebrew](https://brew.sh).
|
||||
|
||||
@@ -35,16 +35,25 @@ Join us on our [**Discord server**](https://discord.gg/X8YWP8w) for a chat.
|
||||
|
||||
`brew install --cask flycast`
|
||||
|
||||
### Xbox One/Series
|
||||
### Xbox One/Series 
|
||||
|
||||
#### Retail:
|
||||
Open [**gamr13's github page**](https://gamr13.github.io/) from your Xbox console.
|
||||
|
||||
#### Dev Mode:
|
||||
Grab the latest build from [**the builds page**](https://flyinghead.github.io/flycast-builds/), or the [**GitHub Actions**](https://github.com/flyinghead/flycast/actions/workflows/uwp.yml). Then install it using the **Xbox Device Portal**.
|
||||
|
||||
### Binaries
|
||||
### Binaries      
|
||||
|
||||
Get fresh builds for your system [**on the builds page**](https://flyinghead.github.io/flycast-builds/).
|
||||
|
||||
**New:** Now automated test results are available as well.
|
||||
|
||||
### Build instructions:
|
||||
`git clone https://github.com/flyinghead/flycast.git`
|
||||
|
||||
`cd flycast`
|
||||
|
||||
`git submodule update --init --recursive`
|
||||
|
||||
`mkdir build && cd build`
|
||||
|
||||
`cmake ..`
|
||||
|
||||
`make`
|
||||
+1
-2
@@ -7,11 +7,10 @@ Here lies the core of our codebase. Everything that's OS inspecific rests here.
|
||||
### Some rudimentary categories are:
|
||||
- hw -- DC Hardware Components Implementation
|
||||
- nullDC.cpp -- Main entry points
|
||||
- khronos -- OpenGL and Vulkan headers
|
||||
- oslib -- Audio drivers
|
||||
- cfg -- Configuration backend structure
|
||||
- reios -- (Our) Implementation of the DreamCast BIOS
|
||||
- deps -- External dependencies
|
||||
- imgread -- Content drivers
|
||||
- rec-* -- Recompilers
|
||||
- rend -- OpenGL and Vulkan renderers
|
||||
- rend -- Graphics renderers and UI
|
||||
@@ -23,19 +23,19 @@
|
||||
#include "deps/lzma/7zCrc.h"
|
||||
#include "deps/lzma/Alloc.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#define kInputBufSize ((size_t)1 << 18)
|
||||
|
||||
static bool crc_tables_generated;
|
||||
|
||||
bool SzArchive::Open(const char* path)
|
||||
bool SzArchive::Open(FILE *file)
|
||||
{
|
||||
SzArEx_Init(&szarchive);
|
||||
|
||||
File_Close(&archiveStream.file);
|
||||
File_Construct(&archiveStream.file);
|
||||
archiveStream.file.file = nowide::fopen(path, "rb");
|
||||
if (archiveStream.file.file == nullptr)
|
||||
return false;
|
||||
archiveStream.file.file = file;
|
||||
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead2_CreateVTable(&lookStream, 0);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "deps/lzma/7zFile.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
class SzArchive : public Archive
|
||||
{
|
||||
@@ -38,9 +39,10 @@ public:
|
||||
ArchiveFile* OpenFile(const char* name) override;
|
||||
ArchiveFile *OpenFileByCrc(u32 crc) override;
|
||||
|
||||
private:
|
||||
bool Open(const char* path) override;
|
||||
protected:
|
||||
bool Open(FILE *file) override;
|
||||
|
||||
private:
|
||||
CSzArEx szarchive;
|
||||
UInt32 block_idx; /* it can have any value before first call (if outBuffer = 0) */
|
||||
Byte *out_buffer; /* it must be 0 before first call for each new archive. */
|
||||
|
||||
@@ -25,11 +25,8 @@ ZipArchive::~ZipArchive()
|
||||
zip_close(zip);
|
||||
}
|
||||
|
||||
bool ZipArchive::Open(const char* path)
|
||||
bool ZipArchive::Open(FILE *file)
|
||||
{
|
||||
FILE *file = nowide::fopen(path, "rb");
|
||||
if (file == nullptr)
|
||||
return false;
|
||||
zip_error_t error;
|
||||
zip_source_t *source = zip_source_filep_create(file, 0, -1, &error);
|
||||
if (source == nullptr)
|
||||
@@ -54,15 +51,16 @@ ArchiveFile* ZipArchive::OpenFile(const char* name)
|
||||
|
||||
struct zip_file *zip_fopen_by_crc(struct zip *za, u32 crc, int flags)
|
||||
{
|
||||
int i, n;
|
||||
zip_uint64_t i;
|
||||
zip_int64_t n;
|
||||
struct zip_stat stat;
|
||||
|
||||
if (crc == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = zip_get_num_files(za);
|
||||
for (i = 0; i < n; i++) {
|
||||
n = zip_get_num_entries(za, 0);
|
||||
for (i = 0; i < (zip_uint64_t)n; i++) {
|
||||
if (zip_stat_index(za, i, flags, &stat) < -1) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -88,3 +86,23 @@ u32 ZipArchiveFile::Read(void* buffer, u32 length)
|
||||
{
|
||||
return zip_fread(zip_file, buffer, length);
|
||||
}
|
||||
|
||||
bool ZipArchive::Open(const void *data, size_t size)
|
||||
{
|
||||
zip_error_t error;
|
||||
zip_source_t *source = zip_source_buffer_create(data, size, 0, &error);
|
||||
if (source == nullptr)
|
||||
return false;
|
||||
zip = zip_open_from_source(source, 0, NULL);
|
||||
if (zip == nullptr)
|
||||
zip_source_free(source);
|
||||
return zip != nullptr;
|
||||
}
|
||||
|
||||
ArchiveFile *ZipArchive::OpenFirstFile()
|
||||
{
|
||||
zip_file *zipFile = zip_fopen_index(zip, 0, 0);
|
||||
if (zipFile == nullptr)
|
||||
return nullptr;
|
||||
return new ZipArchiveFile(zipFile);
|
||||
}
|
||||
@@ -32,9 +32,13 @@ public:
|
||||
ArchiveFile* OpenFile(const char* name) override;
|
||||
ArchiveFile* OpenFileByCrc(u32 crc) override;
|
||||
|
||||
private:
|
||||
bool Open(const char* path) override;
|
||||
bool Open(const void *data, size_t size);
|
||||
ArchiveFile *OpenFirstFile();
|
||||
|
||||
protected:
|
||||
bool Open(FILE *file) override;
|
||||
|
||||
private:
|
||||
struct zip *zip;
|
||||
};
|
||||
|
||||
|
||||
+49
-12
@@ -22,24 +22,61 @@
|
||||
#include "archive.h"
|
||||
#include "7zArchive.h"
|
||||
#include "ZipArchive.h"
|
||||
#include "oslib/storage.h"
|
||||
|
||||
Archive *OpenArchive(const char *path)
|
||||
Archive *OpenArchive(const std::string& path)
|
||||
{
|
||||
std::string base_path(path);
|
||||
|
||||
Archive *sz_archive = new SzArchive();
|
||||
if (sz_archive->Open(base_path.c_str()) || sz_archive->Open((base_path + ".7z").c_str()) || sz_archive->Open((base_path + ".7Z").c_str()))
|
||||
return sz_archive;
|
||||
delete sz_archive;
|
||||
|
||||
FILE *file = nullptr;
|
||||
hostfs::FileInfo fileInfo;
|
||||
try {
|
||||
fileInfo = hostfs::storage().getFileInfo(path);
|
||||
if (!fileInfo.isDirectory)
|
||||
file = hostfs::storage().openFile(path, "rb");
|
||||
} catch (const hostfs::StorageException& e) {
|
||||
}
|
||||
if (file == nullptr)
|
||||
{
|
||||
file = hostfs::storage().openFile(path + ".7z", "rb");
|
||||
if (file == nullptr)
|
||||
file = hostfs::storage().openFile(path + ".7Z", "rb");
|
||||
}
|
||||
if (file != nullptr)
|
||||
{
|
||||
Archive *sz_archive = new SzArchive();
|
||||
if (sz_archive->Open(file))
|
||||
return sz_archive;
|
||||
delete sz_archive;
|
||||
file = nullptr;
|
||||
}
|
||||
// Retry as a zip file
|
||||
try {
|
||||
if (!fileInfo.isDirectory)
|
||||
file = hostfs::storage().openFile(path, "rb");
|
||||
} catch (const hostfs::StorageException& e) {
|
||||
}
|
||||
if (file == nullptr)
|
||||
{
|
||||
file = hostfs::storage().openFile(path + ".zip", "rb");
|
||||
if (file == nullptr)
|
||||
{
|
||||
file = hostfs::storage().openFile(path + ".ZIP", "rb");
|
||||
if (file == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Archive *zip_archive = new ZipArchive();
|
||||
if (zip_archive->Open(base_path.c_str()) || zip_archive->Open((base_path + ".zip").c_str()) || zip_archive->Open((base_path + ".ZIP").c_str()))
|
||||
if (zip_archive->Open(file))
|
||||
return zip_archive;
|
||||
delete zip_archive;
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Archive::Open(const char* path)
|
||||
{
|
||||
FILE *file = nowide::fopen(path, "rb");
|
||||
if (file == nullptr)
|
||||
return false;
|
||||
return Open(file);
|
||||
}
|
||||
|
||||
@@ -36,10 +36,13 @@ public:
|
||||
virtual ArchiveFile *OpenFile(const char *name) = 0;
|
||||
virtual ArchiveFile *OpenFileByCrc(u32 crc) = 0;
|
||||
|
||||
friend Archive *OpenArchive(const char *path);
|
||||
protected:
|
||||
virtual bool Open(FILE *file) = 0;
|
||||
|
||||
private:
|
||||
virtual bool Open(const char *name) = 0;
|
||||
bool Open(const char *name);
|
||||
|
||||
friend Archive *OpenArchive(const std::string& path);
|
||||
};
|
||||
|
||||
Archive *OpenArchive(const char *path);
|
||||
Archive *OpenArchive(const std::string& path);
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "rzip.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
const u8 RZipHeader[8] = { '#', 'R', 'Z', 'I', 'P', 'v', 1, '#' };
|
||||
|
||||
bool RZipFile::Open(const std::string& path, bool write)
|
||||
@@ -52,7 +54,7 @@ bool RZipFile::Open(const std::string& path, bool write)
|
||||
}
|
||||
else
|
||||
{
|
||||
maxChunkSize = 1024 * 1024;
|
||||
maxChunkSize = 1_MB;
|
||||
if (std::fwrite(RZipHeader, sizeof(RZipHeader), 1, file) != 1
|
||||
|| std::fwrite(&maxChunkSize, sizeof(maxChunkSize), 1, file) != 1
|
||||
|| std::fwrite(&size, sizeof(size), 1, file) != 1)
|
||||
|
||||
+7
-129
@@ -1,120 +1,4 @@
|
||||
/*
|
||||
reicast build options
|
||||
|
||||
Reicast can support a lot of stuff, and this is an attempt
|
||||
to organize the build time options
|
||||
|
||||
Option categories
|
||||
|
||||
BUILD_* - BUILD_COMPILER, etc...
|
||||
definitions about the build machine
|
||||
|
||||
HOST_*
|
||||
definitions about the host machine
|
||||
|
||||
FEAT_*
|
||||
definitions about the features that this build targets
|
||||
This is higly related to HOST_*, but it's for options that might
|
||||
or might not be avaiable depending on the target host, or that
|
||||
features that are irrelevant of the host
|
||||
|
||||
Eg, Alsa, Pulse Audio and OSS might sense as HOST dedinitions
|
||||
but it usually makes more sense to detect them as runtime. In
|
||||
that context, HOST_ALSA makes no sense because the host might
|
||||
or might not have alsa installed/ running
|
||||
|
||||
MMU makes no sense as a HOST definition at all, so it should
|
||||
be FEAT_HAS_MMU
|
||||
|
||||
TARGET_*
|
||||
A preconfigured default. Eg TARGET_WIN86.
|
||||
|
||||
Naming of options, option values, and how to use them
|
||||
|
||||
for options that makes sense to have a list of values
|
||||
{CATEGORY}_{OPTION}
|
||||
{OPTION}_{VALUE}
|
||||
|
||||
eg.
|
||||
BUILD_COMPILER == COMPILER_GCC, HOST_CPU != CPU_X64, ...
|
||||
|
||||
for options that are boolean
|
||||
{CATEGORY}_IS_{OPTION} or {CATEGORY}_HAS_{OPTION}
|
||||
|
||||
Evaluates to 0 or 1
|
||||
|
||||
If an configuration cannot be neatly split into a set of
|
||||
of orthogonal options, then it makes sense to break things
|
||||
to "sets" or have a hierarchy of options.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
In the beggining it made sense to have an audio backend
|
||||
per operating system. It made sense to have it depend
|
||||
on HOST_OS and seleect DirectSound or alsa.
|
||||
|
||||
// no option needed
|
||||
|
||||
Then, as android was introduced, which also uses OS_LINUX
|
||||
atm, the audio could have been made an option. It could be
|
||||
a HOST_* option, or FEAT_* one. I'd prefer FEAT_*.
|
||||
FEAT_* makes more sense as future wise we might want
|
||||
to support multiple backends.
|
||||
|
||||
FEAT_AUDIO_BACKEND
|
||||
AUDIO_BACKEND_NONE
|
||||
AUDIO_BACKEND_DS
|
||||
AUDIO_BACKEND_ALSA
|
||||
AUDIO_BACKEND_ANDROID
|
||||
|
||||
Used like
|
||||
#if FEAT_AUDIO_BACKEND == AUDIO_BACKEND_DS ....
|
||||
|
||||
At some point, we might have multiple audio backends that
|
||||
can be compiled in and autodetected/selected at runtime.
|
||||
In that case, it might make sense to have the options like
|
||||
|
||||
FEAT_HAS_ALSA
|
||||
FEAT_HAS_DIRECTSOUND
|
||||
FEAT_HAS_ANDROID_AUDIO
|
||||
|
||||
or
|
||||
FEAT_HAS_AUDIO_ALSA
|
||||
FEAT_HAS_AUDIO_DS
|
||||
FEAT_HAS_AUDIO_ANDROID
|
||||
|
||||
The none option might or might not make sense. In this
|
||||
case it can be removed, as it should always be avaiable.
|
||||
|
||||
Guidelines
|
||||
----------
|
||||
|
||||
General rule of thumb, don't overcomplicate things. Start
|
||||
with a simple option, and then make it more complicated
|
||||
as new uses apply (see the example above)
|
||||
|
||||
Don't use too long names, don't use too cryptic names.
|
||||
Most team developers should be able to understand or
|
||||
figure out most of the acronyms used.
|
||||
|
||||
Try to be consistent on the acronyms across all definitions
|
||||
|
||||
Code shouldn't depend on build level options whenever possible
|
||||
|
||||
Generally, the file should compile even if the option/module is
|
||||
disabled. This makes makefiles etc much easier to write
|
||||
|
||||
TARGET_* options should generally only be used in this file
|
||||
|
||||
The current source is *not* good example of these guidelines
|
||||
|
||||
We'll try to be smart and figure out some options/defaults on this file
|
||||
but this shouldn't get too complicated
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
//#define STRICT_MODE
|
||||
#ifndef STRICT_MODE
|
||||
#define FAST_MMU
|
||||
@@ -126,6 +10,7 @@
|
||||
#define DC_PLATFORM_NAOMI 2
|
||||
#define DC_PLATFORM_NAOMI2 3
|
||||
#define DC_PLATFORM_ATOMISWAVE 4
|
||||
#define DC_PLATFORM_SYSTEMSP 5
|
||||
|
||||
//HOST_CPU
|
||||
#define CPU_X86 0x20000001
|
||||
@@ -140,7 +25,6 @@
|
||||
//FEAT_SHREC, FEAT_AREC, FEAT_DSPREC
|
||||
#define DYNAREC_NONE 0x40000001
|
||||
#define DYNAREC_JIT 0x40000002
|
||||
#define DYNAREC_CPP 0x40000003
|
||||
|
||||
//automatic
|
||||
|
||||
@@ -170,12 +54,6 @@
|
||||
#define FEAT_DSPREC DYNAREC_NONE
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NO_JIT)
|
||||
#define FEAT_SHREC DYNAREC_CPP
|
||||
#define FEAT_AREC DYNAREC_NONE
|
||||
#define FEAT_DSPREC DYNAREC_NONE
|
||||
#endif
|
||||
|
||||
#ifdef __SWITCH__
|
||||
#define FEAT_NO_RWX_PAGES
|
||||
#endif
|
||||
@@ -226,12 +104,12 @@
|
||||
#define USE_GGPO
|
||||
#endif
|
||||
|
||||
#if !defined(__ANDROID__) && !defined(TARGET_IPHONE) && !defined(TARGET_UWP) \
|
||||
&& !defined(__SWITCH__) && !defined(LIBRETRO) && !defined(__NetBSD__) && !defined(__OpenBSD__)
|
||||
#define NAOMI_MULTIBOARD
|
||||
#endif
|
||||
|
||||
// TARGET PLATFORM
|
||||
|
||||
#define RAM_SIZE_MAX (32*1024*1024)
|
||||
#define VRAM_SIZE_MAX (16*1024*1024)
|
||||
#define ARAM_SIZE_MAX (8*1024*1024)
|
||||
|
||||
#define GD_CLOCK 33868800 //GDROM XTAL -- 768fs
|
||||
#define AICA_CORE_CLOCK (GD_CLOCK * 4 / 3) //[45158400] GD->PLL 3:4 -> AICA CORE -- 1024fs
|
||||
#define AICA_ARM_CLOCK (AICA_CORE_CLOCK / 2) //[22579200] AICA CORE -> PLL 2:1 -> ARM
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ bool cfgLoadBool(const std::string& section, const std::string& key, bool def);
|
||||
void cfgSetVirtual(const std::string& section, const std::string& key, const std::string& value);
|
||||
bool cfgIsVirtual(const std::string& section, const std::string& key);
|
||||
|
||||
bool ParseCommandLine(int argc, char *argv[]);
|
||||
void ParseCommandLine(int argc, char *argv[]);
|
||||
|
||||
void cfgSetAutoSave(bool autoSave);
|
||||
bool cfgHasSection(const std::string& section);
|
||||
|
||||
+1
-3
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
#include "cfg/cfg.h"
|
||||
@@ -87,7 +86,7 @@ static int showhelp()
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ParseCommandLine(int argc,char* argv[])
|
||||
void ParseCommandLine(int argc,char* argv[])
|
||||
{
|
||||
settings.content.path.clear();
|
||||
int cl=argc-2;
|
||||
@@ -141,5 +140,4 @@ bool ParseCommandLine(int argc,char* argv[])
|
||||
arg++;
|
||||
cl--;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
+2
-7
@@ -260,18 +260,13 @@ void ConfigFile::parse(FILE* file)
|
||||
|
||||
void ConfigFile::save(FILE* file)
|
||||
{
|
||||
for (const auto& section_it : this->sections)
|
||||
for (const auto& [section_name, section] : this->sections)
|
||||
{
|
||||
const std::string& section_name = section_it.first;
|
||||
const ConfigSection& section = section_it.second;
|
||||
|
||||
if (!section_name.empty())
|
||||
std::fprintf(file, "[%s]\n", section_name.c_str());
|
||||
|
||||
for (const auto& entry_it : section.entries)
|
||||
for (const auto& [entry_name, entry] : section.entries)
|
||||
{
|
||||
const std::string& entry_name = entry_it.first;
|
||||
const ConfigEntry& entry = entry_it.second;
|
||||
std::fprintf(file, "%s = %s\n", entry_name.c_str(), entry.get_string().c_str());
|
||||
}
|
||||
if (!section_name.empty())
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
namespace emucfg {
|
||||
|
||||
|
||||
+11
-3
@@ -25,7 +25,7 @@ namespace config {
|
||||
// Dynarec
|
||||
|
||||
Option<bool> DynarecEnabled("Dynarec.Enabled", true);
|
||||
Option<bool> DynarecIdleSkip("Dynarec.idleskip", true);
|
||||
Option<int> Sh4Clock("Sh4Clock", 200);
|
||||
|
||||
// General
|
||||
|
||||
@@ -33,7 +33,6 @@ Option<int> Cable("Dreamcast.Cable", 3); // TV Composite
|
||||
Option<int> Region("Dreamcast.Region", 1); // USA
|
||||
Option<int> Broadcast("Dreamcast.Broadcast", 0); // NTSC
|
||||
Option<int> Language("Dreamcast.Language", 1); // English
|
||||
Option<bool> FullMMU("Dreamcast.FullMMU");
|
||||
Option<bool> ForceWindowsCE("Dreamcast.ForceWindowsCE");
|
||||
Option<bool> AutoLoadState("Dreamcast.AutoLoadState");
|
||||
Option<bool> AutoSaveState("Dreamcast.AutoSaveState");
|
||||
@@ -60,6 +59,7 @@ Option<bool> AutoLatency("aica.AutoLatency",
|
||||
|
||||
OptionString AudioBackend("backend", "auto", "audio");
|
||||
AudioVolumeOption AudioVolume;
|
||||
Option<bool> VmuSound("VmuSound", false, "audio");
|
||||
|
||||
// Rendering
|
||||
|
||||
@@ -98,7 +98,7 @@ Option<int> MaxThreads("pvr.MaxThreads", 3);
|
||||
Option<int> AutoSkipFrame("pvr.AutoSkipFrame", 0);
|
||||
Option<int> RenderResolution("rend.Resolution", 480);
|
||||
Option<bool> VSync("rend.vsync", true);
|
||||
Option<int64_t> PixelBufferSize("rend.PixelBufferSize", 512 * 1024 * 1024);
|
||||
Option<int64_t> PixelBufferSize("rend.PixelBufferSize", 512_MB);
|
||||
Option<int> AnisotropicFiltering("rend.AnisotropicFiltering", 1);
|
||||
Option<int> TextureFiltering("rend.TextureFiltering", 0); // Default
|
||||
Option<bool> ThreadedRendering("rend.ThreadedRendering", true);
|
||||
@@ -106,6 +106,11 @@ Option<bool> DupeFrames("rend.DupeFrames", false);
|
||||
Option<int> PerPixelLayers("rend.PerPixelLayers", 32);
|
||||
Option<bool> NativeDepthInterpolation("rend.NativeDepthInterpolation", false);
|
||||
Option<bool> EmulateFramebuffer("rend.EmulateFramebuffer", false);
|
||||
#ifdef VIDEO_ROUTING
|
||||
Option<bool> VideoRouting("rend.VideoRouting", false);
|
||||
Option<bool> VideoRoutingScale("rend.VideoRoutingScale", false);
|
||||
Option<int> VideoRoutingVRes("rend.VideoRoutingVRes", 720);
|
||||
#endif
|
||||
|
||||
// Misc
|
||||
|
||||
@@ -116,6 +121,7 @@ Option<int> GDBPort("Debug.GDBPort", debugger::DEFAULT_PORT);
|
||||
Option<bool> GDBWaitForConnection("Debug.GDBWaitForConnection");
|
||||
Option<bool> UseReios("UseReios");
|
||||
Option<bool> FastGDRomLoad("FastGDRomLoad", false);
|
||||
Option<bool> RamMod32MB("Dreamcast.RamMod32MB", false);
|
||||
|
||||
Option<bool> OpenGlChecks("OpenGlChecks", false, "validate");
|
||||
|
||||
@@ -146,6 +152,7 @@ Option<bool> GGPOChat("GGPOChat", true, "network");
|
||||
Option<bool> GGPOChatTimeoutToggle("GGPOChatTimeoutToggle", true, "network");
|
||||
Option<int> GGPOChatTimeout("GGPOChatTimeout", 10, "network");
|
||||
Option<bool> NetworkOutput("NetworkOutput", false, "network");
|
||||
Option<int> MultiboardSlaves("MultiboardSlaves", 1, "network");
|
||||
|
||||
#ifdef SUPPORT_DISPMANX
|
||||
Option<bool> DispmanxMaintainAspect("maintain_aspect", true, "dispmanx");
|
||||
@@ -180,6 +187,7 @@ std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices {
|
||||
Option<MapleDeviceType>("device4.1", MDT_None, "input"),
|
||||
Option<MapleDeviceType>("device4.2", MDT_None, "input"),
|
||||
};
|
||||
Option<bool> PerGameVmu("PerGameVmu", false, "config");
|
||||
#ifdef _WIN32
|
||||
Option<bool, false> UseRawInput("RawInput", false, "input");
|
||||
#endif
|
||||
|
||||
+34
-25
@@ -21,6 +21,7 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include "cfg.h"
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
#ifdef LIBRETRO
|
||||
@@ -100,10 +101,6 @@ private:
|
||||
friend class Option;
|
||||
};
|
||||
|
||||
// Missing in C++11
|
||||
template <bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
template<typename T, bool PerGameOption = true>
|
||||
class Option : public BaseOption {
|
||||
public:
|
||||
@@ -173,36 +170,36 @@ public:
|
||||
|
||||
protected:
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<U, bool>::value, T>
|
||||
std::enable_if_t<std::is_same_v<U, bool>, T>
|
||||
doLoad(const std::string& section, const std::string& name) const
|
||||
{
|
||||
return cfgLoadBool(section, name, value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<U, int64_t>::value, T>
|
||||
std::enable_if_t<std::is_same<U, int64_t>::value, T>
|
||||
doLoad(const std::string& section, const std::string& name) const
|
||||
{
|
||||
return cfgLoadInt64(section, name, value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<(std::is_integral<U>::value || std::is_enum<U>::value)
|
||||
&& !std::is_same<U, bool>::value && !std::is_same<U, int64_t>::value, T>
|
||||
std::enable_if_t<(std::is_integral_v<U> || std::is_enum_v<U>)
|
||||
&& !std::is_same_v<U, bool> && !std::is_same_v<U, int64_t>, T>
|
||||
doLoad(const std::string& section, const std::string& name) const
|
||||
{
|
||||
return (T)cfgLoadInt(section, name, (int)value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<U, std::string>::value, T>
|
||||
std::enable_if_t<std::is_same_v<U, std::string>, T>
|
||||
doLoad(const std::string& section, const std::string& name) const
|
||||
{
|
||||
return cfgLoadStr(section, name, value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<float, U>::value, T>
|
||||
std::enable_if_t<std::is_same_v<float, U>, T>
|
||||
doLoad(const std::string& section, const std::string& name) const
|
||||
{
|
||||
std::string strValue = cfgLoadStr(section, name, "");
|
||||
@@ -213,7 +210,7 @@ protected:
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<std::vector<std::string>, U>::value, T>
|
||||
std::enable_if_t<std::is_same_v<std::vector<std::string>, U>, T>
|
||||
doLoad(const std::string& section, const std::string& name) const
|
||||
{
|
||||
std::string paths = cfgLoadStr(section, name, "");
|
||||
@@ -272,36 +269,36 @@ protected:
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<U, bool>::value>
|
||||
std::enable_if_t<std::is_same_v<U, bool>>
|
||||
doSave(const std::string& section, const std::string& name) const
|
||||
{
|
||||
cfgSaveBool(section, name, value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<U, int64_t>::value>
|
||||
std::enable_if_t<std::is_same<U, int64_t>::value>
|
||||
doSave(const std::string& section, const std::string& name) const
|
||||
{
|
||||
cfgSaveInt64(section, name, value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<(std::is_integral<U>::value || std::is_enum<U>::value)
|
||||
&& !std::is_same<U, bool>::value && !std::is_same<U, int64_t>::value>
|
||||
std::enable_if_t<(std::is_integral_v<U> || std::is_enum_v<U>)
|
||||
&& !std::is_same_v<U, bool> && !std::is_same_v<U, int64_t>>
|
||||
doSave(const std::string& section, const std::string& name) const
|
||||
{
|
||||
cfgSaveInt(section, name, (int)value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<U, std::string>::value>
|
||||
std::enable_if_t<std::is_same_v<U, std::string>>
|
||||
doSave(const std::string& section, const std::string& name) const
|
||||
{
|
||||
cfgSaveStr(section, name, value);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<float, U>::value>
|
||||
std::enable_if_t<std::is_same_v<float, U>>
|
||||
doSave(const std::string& section, const std::string& name) const
|
||||
{
|
||||
char buf[64];
|
||||
@@ -310,7 +307,7 @@ protected:
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
enable_if_t<std::is_same<std::vector<std::string>, U>::value>
|
||||
std::enable_if_t<std::is_same_v<std::vector<std::string>, U>>
|
||||
doSave(const std::string& section, const std::string& name) const
|
||||
{
|
||||
std::string s;
|
||||
@@ -359,8 +356,9 @@ using OptionString = Option<std::string>;
|
||||
// Dynarec
|
||||
|
||||
extern Option<bool> DynarecEnabled;
|
||||
extern Option<bool> DynarecIdleSkip;
|
||||
constexpr bool DynarecSafeMode = false;
|
||||
#ifndef LIBRETRO
|
||||
extern Option<int> Sh4Clock;
|
||||
#endif
|
||||
|
||||
// General
|
||||
|
||||
@@ -368,7 +366,6 @@ extern Option<int> Cable; // 0 -> VGA, 1 -> VGA, 2 -> RGB, 3 -> TV Composite
|
||||
extern Option<int> Region; // 0 -> JP, 1 -> USA, 2 -> EU, 3 -> default
|
||||
extern Option<int> Broadcast; // 0 -> NTSC, 1 -> PAL, 2 -> PAL/M, 3 -> PAL/N, 4 -> default
|
||||
extern Option<int> Language; // 0 -> JP, 1 -> EN, 2 -> DE, 3 -> FR, 4 -> SP, 5 -> IT, 6 -> default
|
||||
extern Option<bool> FullMMU;
|
||||
extern Option<bool> ForceWindowsCE;
|
||||
extern Option<bool> AutoLoadState;
|
||||
extern Option<bool> AutoSaveState;
|
||||
@@ -409,19 +406,23 @@ public:
|
||||
}
|
||||
};
|
||||
extern AudioVolumeOption AudioVolume;
|
||||
extern Option<bool> VmuSound;
|
||||
|
||||
// Rendering
|
||||
|
||||
class RendererOption : public Option<RenderType> {
|
||||
public:
|
||||
RendererOption()
|
||||
RendererOption() : Option<RenderType>("pvr.rend",
|
||||
#if defined(USE_DX11)
|
||||
: Option<RenderType>("pvr.rend", RenderType::DirectX11) {}
|
||||
RenderType::DirectX11
|
||||
#elif defined(USE_DX9)
|
||||
: Option<RenderType>("pvr.rend", RenderType::DirectX9) {}
|
||||
RenderType::DirectX9
|
||||
#elif !defined(USE_OPENGL)
|
||||
RenderType::Vulkan
|
||||
#else
|
||||
: Option<RenderType>("pvr.rend", RenderType::OpenGL) {}
|
||||
RenderType::OpenGL
|
||||
#endif
|
||||
) {}
|
||||
|
||||
RenderType& operator=(const RenderType& v) { set(v); return value; }
|
||||
|
||||
@@ -467,6 +468,11 @@ extern Option<bool> ThreadedRendering;
|
||||
extern Option<bool> DupeFrames;
|
||||
extern Option<bool> NativeDepthInterpolation;
|
||||
extern Option<bool> EmulateFramebuffer;
|
||||
#ifdef VIDEO_ROUTING
|
||||
extern Option<bool> VideoRouting;
|
||||
extern Option<bool> VideoRoutingScale;
|
||||
extern Option<int> VideoRoutingVRes;
|
||||
#endif
|
||||
|
||||
// Misc
|
||||
|
||||
@@ -477,6 +483,7 @@ extern Option<int> GDBPort;
|
||||
extern Option<bool> GDBWaitForConnection;
|
||||
extern Option<bool> UseReios;
|
||||
extern Option<bool> FastGDRomLoad;
|
||||
extern Option<bool> RamMod32MB;
|
||||
|
||||
extern Option<bool> OpenGlChecks;
|
||||
|
||||
@@ -507,6 +514,7 @@ extern Option<bool> GGPOChat;
|
||||
extern Option<bool> GGPOChatTimeoutToggle;
|
||||
extern Option<int> GGPOChatTimeout;
|
||||
extern Option<bool> NetworkOutput;
|
||||
extern Option<int> MultiboardSlaves;
|
||||
|
||||
#ifdef SUPPORT_DISPMANX
|
||||
extern Option<bool> DispmanxMaintainAspect;
|
||||
@@ -523,6 +531,7 @@ extern Option<int> MouseSensitivity;
|
||||
extern Option<int> VirtualGamepadVibration;
|
||||
extern std::array<Option<MapleDeviceType>, 4> MapleMainDevices;
|
||||
extern std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices;
|
||||
extern Option<bool> PerGameVmu;
|
||||
#ifdef _WIN32
|
||||
extern Option<bool, false> UseRawInput;
|
||||
#else
|
||||
|
||||
+56
-15
@@ -27,6 +27,7 @@
|
||||
#include "cfg/ini.h"
|
||||
#include "cfg/option.h"
|
||||
#include "emulator.h"
|
||||
#include "oslib/storage.h"
|
||||
|
||||
const WidescreenCheat CheatManager::widescreen_cheats[] =
|
||||
{
|
||||
@@ -368,7 +369,7 @@ void CheatManager::setActive(bool active)
|
||||
void CheatManager::loadCheatFile(const std::string& filename)
|
||||
{
|
||||
#ifndef LIBRETRO
|
||||
FILE* cheatfile = nowide::fopen(filename.c_str(), "r");
|
||||
FILE* cheatfile = hostfs::storage().openFile(filename, "r");
|
||||
if (cheatfile == nullptr)
|
||||
{
|
||||
WARN_LOG(COMMON, "Cannot open cheat file '%s'", filename.c_str());
|
||||
@@ -429,13 +430,7 @@ void CheatManager::reset(const std::string& gameId)
|
||||
if (!cheatFile.empty())
|
||||
loadCheatFile(cheatFile);
|
||||
#endif
|
||||
if (gameId == "VF4 FINAL TUNED JAPAN")
|
||||
{
|
||||
setActive(true);
|
||||
cheats.emplace_back(Cheat::Type::setValue, "Skip DIMM version check", true, 16, 0x0007f486, 0xe001); // mov #1, r0
|
||||
cheats.back().builtIn = true;
|
||||
}
|
||||
else if (gameId == "Fixed BOOT strapper") // Extreme Hunting 2
|
||||
if (gameId == "Fixed BOOT strapper") // Extreme Hunting 2
|
||||
{
|
||||
setActive(true);
|
||||
cheats.emplace_back(Cheat::Type::runNextIfEq, "skip netbd check ifeq", true, 32, 0x00067b04, 0);
|
||||
@@ -450,6 +445,55 @@ void CheatManager::reset(const std::string& gameId)
|
||||
cheats.emplace_back(Cheat::Type::setValue, "fix boot", true, 32, 0x00010000, 0x9302d202);
|
||||
cheats.back().builtIn = true;
|
||||
}
|
||||
else if (gameId == "THE KING OF ROUTE66")
|
||||
{
|
||||
setActive(true);
|
||||
cheats.emplace_back(Cheat::Type::setValue, "ignore drive error", true, 32, 0x00023ee0, 0x0009000B); // rts, nop
|
||||
cheats.back().builtIn = true;
|
||||
}
|
||||
else if (gameId.substr(0, 8) == "MKG TKOB")
|
||||
{
|
||||
const auto& setMushikingCheats = [this](u32 addr) {
|
||||
setActive(true);
|
||||
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid1 error", true, 32, addr, 0); // rfid[0].error = 0
|
||||
cheats.back().builtIn = true;
|
||||
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid2 error", true, 32, addr + 0x48, 0); // rfid[1].error = 0
|
||||
cheats.back().builtIn = true;
|
||||
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid1 status", true, 32, addr + 8, 0); // rfid[0].data18 = 0
|
||||
cheats.back().builtIn = true;
|
||||
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid2 status", true, 32, addr + 0x50, 0); // rfid[1].data18 = 0
|
||||
cheats.back().builtIn = true;
|
||||
};
|
||||
if (gameId == "MKG TKOB 2 EXP VER1.001-") // mushi2eo
|
||||
setMushikingCheats(0x6fe1bc);
|
||||
else if (gameId == "MKG TKOB 2 JPN VER2.001-") // mushik2e
|
||||
setMushikingCheats(0x6ffe54);
|
||||
else if (gameId == "MKG TKOB 2K3 2ND VER1.003-")// mushike
|
||||
setMushikingCheats(0x4ad7ec);
|
||||
else if (gameId == "MKG TKOB 4 JPN VER2.000-") // mushik4e
|
||||
setMushikingCheats(0xb0e538);
|
||||
else if (gameId == "MKG TKOB 2K3 2ND VER1.002-")// mushikeo
|
||||
setMushikingCheats(0x4ad56c);
|
||||
else if (gameId == "MKG TKOB 2K3 2ND KOR VER1.000-") // mushikk
|
||||
setMushikingCheats(0x4ac9b8);
|
||||
else if (gameId == "MKG TKOB 2K3 2ND CHN VER1.000-") // mushikc
|
||||
setMushikingCheats(0x4aa9b8);
|
||||
else if (gameId == "MKG TKOB 2 KOR VER1.000-") // mushik2k
|
||||
setMushikingCheats(0x706084);
|
||||
}
|
||||
else if (gameId == "T-8120N") // Dave Mirra BMX (US)
|
||||
{
|
||||
setActive(true);
|
||||
cheats.emplace_back(Cheat::Type::setValue, "fix main loop time", true, 32, 0x0030b8cc, 0x42040000); // 33.0 ms
|
||||
cheats.back().builtIn = true;
|
||||
}
|
||||
else if (gameId == "T8120D 50") // Dave Mirra BMX (EU)
|
||||
{
|
||||
setActive(true);
|
||||
cheats.emplace_back(Cheat::Type::setValue, "fix main loop time", true, 32, 0x003011cc, 0x42200000); // 40.0 ms
|
||||
cheats.back().builtIn = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (config::WidescreenGameHacks)
|
||||
{
|
||||
@@ -471,10 +515,7 @@ void CheatManager::reset(const std::string& gameId)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string romName = get_file_basename(settings.content.path);
|
||||
size_t folder_pos = get_last_slash_pos(romName);
|
||||
if (folder_pos != std::string::npos)
|
||||
romName = romName.substr(folder_pos + 1);
|
||||
std::string romName = get_file_basename(settings.content.fileName);
|
||||
|
||||
for (int i = 0; naomi_widescreen_cheats[i].game_id != nullptr; i++)
|
||||
{
|
||||
@@ -489,7 +530,7 @@ void CheatManager::reset(const std::string& gameId)
|
||||
}
|
||||
}
|
||||
if (widescreen_cheat != nullptr)
|
||||
for (size_t i = 0; i < ARRAY_SIZE(widescreen_cheat->addresses) && widescreen_cheat->addresses[i] != 0; i++)
|
||||
for (size_t i = 0; i < std::size(widescreen_cheat->addresses) && widescreen_cheat->addresses[i] != 0; i++)
|
||||
verify(widescreen_cheat->addresses[i] < RAM_SIZE);
|
||||
}
|
||||
setActive(active);
|
||||
@@ -530,7 +571,7 @@ void CheatManager::apply()
|
||||
{
|
||||
if (widescreen_cheat != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(widescreen_cheat->addresses) && widescreen_cheat->addresses[i] != 0; i++)
|
||||
for (size_t i = 0; i < std::size(widescreen_cheat->addresses) && widescreen_cheat->addresses[i] != 0; i++)
|
||||
{
|
||||
u32 address = widescreen_cheat->addresses[i];
|
||||
u32 curVal = readRam(address, 32);
|
||||
@@ -898,7 +939,7 @@ void CheatManager::saveCheatFile(const std::string& filename)
|
||||
i++;
|
||||
}
|
||||
cfg.set_int("", "cheats", i);
|
||||
FILE *fp = nowide::fopen(filename.c_str(), "w");
|
||||
FILE *fp = hostfs::storage().openFile(filename.c_str(), "w");
|
||||
if (fp == nullptr)
|
||||
throw FlycastException("Can't save cheat file");
|
||||
cfg.save(fp);
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct WidescreenCheat
|
||||
{
|
||||
const char *game_id;
|
||||
|
||||
+37
-39
@@ -34,9 +34,6 @@
|
||||
#define SIGBUS 7
|
||||
#endif
|
||||
|
||||
#define SWAP_32(a) ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))
|
||||
#define SWAP_16(a) ((((a) & 0x00ff) << 8) | (((a) & 0xff00) >> 8))
|
||||
|
||||
const std::array<Sh4RegType, 59> Sh4RegList {
|
||||
reg_r0,
|
||||
reg_r1,
|
||||
@@ -76,6 +73,24 @@ const std::array<Sh4RegType, 59> Sh4RegList {
|
||||
class DebugAgent
|
||||
{
|
||||
public:
|
||||
struct Breakpoint {
|
||||
enum Type
|
||||
{
|
||||
BP_TYPE_SOFTWARE_BREAK,
|
||||
BP_TYPE_HARDWARE_BREAK,
|
||||
BP_TYPE_WRITE_WATCHPOINT,
|
||||
BP_TYPE_READ_WATCHPOINT,
|
||||
BP_TYPE_ACCESS_WATCHPOINT,
|
||||
BP_TYPE_COUNT
|
||||
};
|
||||
|
||||
Breakpoint() = default;
|
||||
Breakpoint(u16 type, u32 addr) : addr(addr), type(type) { }
|
||||
u32 addr = 0;
|
||||
u16 type = 0;
|
||||
u16 savedOp = 0;
|
||||
};
|
||||
|
||||
void doContinue(u32 pc = 1)
|
||||
{
|
||||
if (pc != 1)
|
||||
@@ -85,20 +100,20 @@ public:
|
||||
|
||||
void step()
|
||||
{
|
||||
bool restoreBreakpoint = removeMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, Sh4cntx.pc, 2);
|
||||
bool restoreBreakpoint = removeMatchpoint(Breakpoint::BP_TYPE_SOFTWARE_BREAK, Sh4cntx.pc, 2);
|
||||
u32 savedPc = Sh4cntx.pc;
|
||||
emu.step();
|
||||
if (restoreBreakpoint)
|
||||
insertMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, savedPc, 2);
|
||||
insertMatchpoint(Breakpoint::BP_TYPE_SOFTWARE_BREAK, savedPc, 2);
|
||||
}
|
||||
|
||||
void stepRange(u32 from, u32 to)
|
||||
{
|
||||
bool restoreBreakpoint = removeMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, Sh4cntx.pc, 2);
|
||||
bool restoreBreakpoint = removeMatchpoint(Breakpoint::BP_TYPE_SOFTWARE_BREAK, Sh4cntx.pc, 2);
|
||||
u32 savedPc = Sh4cntx.pc;
|
||||
emu.stepRange(from, to);
|
||||
if (restoreBreakpoint)
|
||||
insertMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, savedPc, 2);
|
||||
insertMatchpoint(Breakpoint::BP_TYPE_SOFTWARE_BREAK, savedPc, 2);
|
||||
}
|
||||
|
||||
int readAllRegs(u32 **regs)
|
||||
@@ -107,9 +122,9 @@ public:
|
||||
for (u32 i = 0; i < Sh4RegList.size(); i++)
|
||||
{
|
||||
if (Sh4RegList[i] == reg_sr_status)
|
||||
allregs[i] = SWAP_32(sh4_sr_GetFull());
|
||||
allregs[i] = sh4_sr_GetFull();
|
||||
else if (Sh4RegList[i] != NoReg)
|
||||
allregs[i] = SWAP_32(*GetRegPtr(Sh4RegList[i]));
|
||||
allregs[i] = *GetRegPtr(Sh4RegList[i]);
|
||||
}
|
||||
*regs = &allregs[0];
|
||||
return allregs.size();
|
||||
@@ -119,7 +134,7 @@ public:
|
||||
{
|
||||
for (u32 i = 0; i < Sh4RegList.size(); i++)
|
||||
if (Sh4RegList[i] != NoReg)
|
||||
*GetRegPtr(Sh4RegList[i]) = SWAP_32(regs[i]);
|
||||
*GetRegPtr(Sh4RegList[i]) = regs[i];
|
||||
}
|
||||
|
||||
u32 readReg(u32 regNum)
|
||||
@@ -128,9 +143,9 @@ public:
|
||||
return 0;
|
||||
Sh4RegType reg = Sh4RegList[regNum];
|
||||
if (reg == reg_sr_status)
|
||||
return SWAP_32(sh4_sr_GetFull());
|
||||
return sh4_sr_GetFull();
|
||||
if (reg != NoReg)
|
||||
return SWAP_32(*GetRegPtr(reg));
|
||||
return *GetRegPtr(reg);
|
||||
return 0;
|
||||
}
|
||||
void writeReg(u32 regNum, u32 value)
|
||||
@@ -139,9 +154,9 @@ public:
|
||||
return;
|
||||
Sh4RegType reg = Sh4RegList[regNum];
|
||||
if (reg == reg_sr_status)
|
||||
sh4_sr_SetFull(SWAP_32(value));
|
||||
sh4_sr_SetFull(value);
|
||||
else if (reg != NoReg)
|
||||
*GetRegPtr(reg) = SWAP_32(value);
|
||||
*GetRegPtr(reg) = value;
|
||||
}
|
||||
|
||||
const u8 *readMem(u32 addr, u32 len)
|
||||
@@ -153,14 +168,14 @@ public:
|
||||
{
|
||||
if (len >= 4 && (addr & 3) == 0)
|
||||
{
|
||||
*(u32 *)p = SWAP_32(ReadMem32_nommu(addr));
|
||||
*(u32 *)p = ReadMem32_nommu(addr);
|
||||
addr += 4;
|
||||
len -= 4;
|
||||
p += 4;
|
||||
}
|
||||
else if (len >= 2 && (addr & 1) == 0)
|
||||
{
|
||||
*(u16 *)p = SWAP_16(ReadMem16_nommu(addr));
|
||||
*(u16 *)p = ReadMem16_nommu(addr);
|
||||
addr += 2;
|
||||
len -= 2;
|
||||
p += 2;
|
||||
@@ -182,14 +197,14 @@ public:
|
||||
{
|
||||
if (len >= 4 && (addr & 3) == 0)
|
||||
{
|
||||
WriteMem32_nommu(addr, SWAP_32(*(u32 *)p));
|
||||
WriteMem32_nommu(addr, *(u32 *)p);
|
||||
addr += 4;
|
||||
len -= 4;
|
||||
p += 4;
|
||||
}
|
||||
else if (len >= 2 && (addr & 3) == 0)
|
||||
{
|
||||
WriteMem16_nommu(addr, SWAP_16(*(u16 *)p));
|
||||
WriteMem16_nommu(addr, *(u16 *)p);
|
||||
addr += 2;
|
||||
len -= 2;
|
||||
p += 2;
|
||||
@@ -202,9 +217,9 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
bool insertMatchpoint(char type, u32 addr, u32 len)
|
||||
bool insertMatchpoint(Breakpoint::Type type, u32 addr, u32 len)
|
||||
{
|
||||
if (type == 0 && len != 2) {
|
||||
if (type == Breakpoint::BP_TYPE_SOFTWARE_BREAK && len != 2) {
|
||||
WARN_LOG(COMMON, "insertMatchpoint: length != 2: %d", len);
|
||||
return false;
|
||||
}
|
||||
@@ -216,9 +231,9 @@ public:
|
||||
WriteMem16_nommu(addr, 0xC308); // trapa #0x20
|
||||
return true;
|
||||
}
|
||||
bool removeMatchpoint(char type, u32 addr, u32 len)
|
||||
bool removeMatchpoint(Breakpoint::Type type, u32 addr, u32 len)
|
||||
{
|
||||
if (type == 0 && len != 2) {
|
||||
if (type == Breakpoint::BP_TYPE_SOFTWARE_BREAK && len != 2) {
|
||||
WARN_LOG(COMMON, "removeMatchpoint: length != 2: %d", len);
|
||||
return false;
|
||||
}
|
||||
@@ -327,23 +342,6 @@ public:
|
||||
|
||||
u32 exception = 0;
|
||||
|
||||
struct Breakpoint {
|
||||
enum Type
|
||||
{
|
||||
BP_TYPE_SOFTWARE_BREAK,
|
||||
BP_TYPE_HARDWARE_BREAK,
|
||||
BP_TYPE_WRITE_WATCHPOINT,
|
||||
BP_TYPE_READ_WATCHPOINT,
|
||||
BP_TYPE_ACCESS_WATCHPOINT,
|
||||
BP_TYPE_COUNT
|
||||
};
|
||||
|
||||
Breakpoint() = default;
|
||||
Breakpoint(u16 type, u32 addr) : addr(addr), type(type) { }
|
||||
u32 addr = 0;
|
||||
u16 type = 0;
|
||||
u16 savedOp = 0;
|
||||
};
|
||||
std::map<u32, Breakpoint> breakpoints[Breakpoint::Type::BP_TYPE_COUNT];
|
||||
std::vector<std::pair<u32, u32>> stack;
|
||||
};
|
||||
+52
-25
@@ -103,7 +103,7 @@ public:
|
||||
if (config::GDBWaitForConnection)
|
||||
{
|
||||
DEBUG_LOG(COMMON, "Waiting for GDB connection...");
|
||||
agent.interrupt();
|
||||
agentInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,18 +198,22 @@ private:
|
||||
{
|
||||
NOTICE_LOG(NETWORK, "gdb: client connection");
|
||||
attached = true;
|
||||
agent.interrupt();
|
||||
agentInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void readCommand()
|
||||
{
|
||||
if (postDebugTrapNeeded)
|
||||
{
|
||||
postDebugTrapNeeded = false;
|
||||
agent.postDebugTrap();
|
||||
}
|
||||
try {
|
||||
try {
|
||||
if (postDebugTrapNeeded)
|
||||
{
|
||||
postDebugTrapNeeded = false;
|
||||
try {
|
||||
agent.postDebugTrap();
|
||||
} catch (const FlycastException& e) {
|
||||
throw Error(e.what());
|
||||
}
|
||||
}
|
||||
std::string packet = recvPacket();
|
||||
if (packet.empty())
|
||||
return;
|
||||
@@ -539,7 +543,7 @@ private:
|
||||
// Tell the remote stub about features supported by GDB,
|
||||
// and query the stub for features it supports
|
||||
char qsupported[128];
|
||||
sprintf_s(qsupported, 128, "PacketSize=%i;vContSupported+", MAX_PACKET_LEN);
|
||||
snprintf(qsupported, 128, "PacketSize=%i;vContSupported+", MAX_PACKET_LEN);
|
||||
sendPacket(qsupported);
|
||||
}
|
||||
else if (pkt.rfind("qSymbol:", 0) == 0)
|
||||
@@ -626,7 +630,7 @@ private:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARN_LOG(COMMON, "vCont action not supported %s", pkt[6], pkt.c_str());
|
||||
WARN_LOG(COMMON, "vCont action not supported %s", pkt.c_str());
|
||||
}
|
||||
}
|
||||
else if (pkt.rfind("vFile:", 0) == 0)
|
||||
@@ -667,15 +671,23 @@ private:
|
||||
|
||||
void step(u32 what = 0)
|
||||
{
|
||||
agent.step();
|
||||
sendPacket("S05");
|
||||
try {
|
||||
agent.step();
|
||||
sendPacket("S05");
|
||||
} catch (const FlycastException& e) {
|
||||
throw Error(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void stepRange(u32 from, u32 to)
|
||||
{
|
||||
sendPacket("OK");
|
||||
agent.stepRange(from, to);
|
||||
sendPacket("S05");
|
||||
try {
|
||||
sendPacket("OK");
|
||||
agent.stepRange(from, to);
|
||||
sendPacket("S05");
|
||||
} catch (const FlycastException& e) {
|
||||
throw Error(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void insertMatchpoint(const std::string& pkt)
|
||||
@@ -688,22 +700,23 @@ private:
|
||||
sendPacket("E01");
|
||||
}
|
||||
switch (type) {
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK: // soft bp
|
||||
if (agent.insertMatchpoint(0, addr, len))
|
||||
case DebugAgent::Breakpoint::BP_TYPE_SOFTWARE_BREAK: // soft bp
|
||||
if (agent.insertMatchpoint(DebugAgent::Breakpoint::BP_TYPE_SOFTWARE_BREAK,
|
||||
addr, len))
|
||||
sendPacket("OK");
|
||||
else
|
||||
sendPacket("E01");
|
||||
break;
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_HARDWARE_BREAK: // hardware bp
|
||||
case DebugAgent::Breakpoint::BP_TYPE_HARDWARE_BREAK: // hardware bp
|
||||
sendPacket("");
|
||||
break;
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_WRITE_WATCHPOINT: // write watchpoint
|
||||
case DebugAgent::Breakpoint::BP_TYPE_WRITE_WATCHPOINT: // write watchpoint
|
||||
sendPacket("");
|
||||
break;
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_READ_WATCHPOINT: // read watchpoint
|
||||
case DebugAgent::Breakpoint::BP_TYPE_READ_WATCHPOINT: // read watchpoint
|
||||
sendPacket("");
|
||||
break;
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_ACCESS_WATCHPOINT: // access watchpoint
|
||||
case DebugAgent::Breakpoint::BP_TYPE_ACCESS_WATCHPOINT: // access watchpoint
|
||||
sendPacket("");
|
||||
break;
|
||||
default:
|
||||
@@ -723,7 +736,8 @@ private:
|
||||
}
|
||||
switch (type) {
|
||||
case 0: // soft bp
|
||||
if (agent.removeMatchpoint(0, addr, len))
|
||||
if (agent.removeMatchpoint(DebugAgent::Breakpoint::BP_TYPE_SOFTWARE_BREAK,
|
||||
addr, len))
|
||||
sendPacket("OK");
|
||||
else
|
||||
sendPacket("E01");
|
||||
@@ -748,7 +762,7 @@ private:
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
u32 signal = agent.interrupt();
|
||||
u32 signal = agentInterrupt();
|
||||
char s[10];
|
||||
sprintf(s, "S%02x", signal);
|
||||
sendPacket(s);
|
||||
@@ -888,6 +902,15 @@ private:
|
||||
throw Error("I/O error");
|
||||
}
|
||||
|
||||
u32 agentInterrupt()
|
||||
{
|
||||
try {
|
||||
return agent.interrupt();
|
||||
} catch (const FlycastException& e) {
|
||||
throw Error(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool initialised = false;
|
||||
bool stopRequested = false;
|
||||
bool attached = false;
|
||||
@@ -932,8 +955,12 @@ static void emuEventCallback(Event event, void *)
|
||||
switch (event)
|
||||
{
|
||||
case Event::Resume:
|
||||
if (!gdbServer.isRunning())
|
||||
gdbServer.run();
|
||||
try {
|
||||
if (!gdbServer.isRunning())
|
||||
gdbServer.run();
|
||||
} catch (const GdbServer::Error& e) {
|
||||
ERROR_LOG(COMMON, "%s", e.what());
|
||||
}
|
||||
break;
|
||||
case Event::Terminate:
|
||||
gdbServer.stop();
|
||||
|
||||
+1
-1
Submodule core/deps/SDL updated: f070c83a60...cc016b0046.
Submodule
+1
Submodule core/deps/Spout added at ce94918ea3.
Submodule
+1
Submodule core/deps/Syphon added at 486dd8e4ef.
+1
-1
Submodule core/deps/Vulkan-Headers updated: b75e5a02b6...85c2334e92.
Submodule core/deps/VulkanMemoryAllocator updated: a6bfc23725...6eb62e1515.
+1
-1
Submodule core/deps/breakpad updated: 4c3d5fce1a...1ab24bcc81.
+1
-1
Submodule core/deps/glslang updated: 10423ec659...76b52ebf77.
+156
-106
@@ -3,14 +3,18 @@
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
|
||||
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
||||
@@ -27,6 +31,7 @@
|
||||
// 2016-05-07: DirectX11: Disabling depth-write.
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx11.h"
|
||||
|
||||
// DirectX
|
||||
@@ -37,31 +42,47 @@
|
||||
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||
#endif
|
||||
|
||||
// DirectX data
|
||||
static ID3D11Device* g_pd3dDevice = NULL;
|
||||
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
||||
static IDXGIFactory* g_pFactory = NULL;
|
||||
static ID3D11Buffer* g_pVB = NULL;
|
||||
static ID3D11Buffer* g_pIB = NULL;
|
||||
static ID3D11VertexShader* g_pVertexShader = NULL;
|
||||
static ID3D11InputLayout* g_pInputLayout = NULL;
|
||||
static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
|
||||
static ID3D11PixelShader* g_pPixelShader = NULL;
|
||||
ID3D11SamplerState* g_pFontSampler = NULL;
|
||||
ID3D11SamplerState* g_pTextureSampler = NULL;
|
||||
ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
||||
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
||||
static ID3D11BlendState* g_pBlendState = NULL;
|
||||
static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
|
||||
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
||||
// DirectX11 data
|
||||
struct ImGui_ImplDX11_Data
|
||||
{
|
||||
ID3D11Device* pd3dDevice;
|
||||
ID3D11DeviceContext* pd3dDeviceContext;
|
||||
IDXGIFactory* pFactory;
|
||||
ID3D11Buffer* pVB;
|
||||
ID3D11Buffer* pIB;
|
||||
ID3D11VertexShader* pVertexShader;
|
||||
ID3D11InputLayout* pInputLayout;
|
||||
ID3D11Buffer* pVertexConstantBuffer;
|
||||
ID3D11PixelShader* pPixelShader;
|
||||
ID3D11SamplerState* pFontSampler;
|
||||
ID3D11SamplerState* pTextureSampler;
|
||||
ID3D11ShaderResourceView* pFontTextureView;
|
||||
ID3D11RasterizerState* pRasterizerState;
|
||||
ID3D11BlendState* pBlendState;
|
||||
ID3D11DepthStencilState* pDepthStencilState;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER
|
||||
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct VERTEX_CONSTANT_BUFFER_DX11
|
||||
{
|
||||
float mvp[4][4];
|
||||
};
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3D11_VIEWPORT vp;
|
||||
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
||||
@@ -75,23 +96,23 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
|
||||
// Setup shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
ctx->IASetInputLayout(g_pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetInputLayout(bd->pInputLayout);
|
||||
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
|
||||
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
ctx->VSSetShader(g_pVertexShader, NULL, 0);
|
||||
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
||||
ctx->PSSetShader(g_pPixelShader, NULL, 0);
|
||||
ctx->GSSetShader(NULL, NULL, 0);
|
||||
ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
|
||||
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||
ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
|
||||
ctx->GSSetShader(nullptr, nullptr, 0);
|
||||
ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||
|
||||
// Setup blend state
|
||||
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
||||
ctx->RSSetState(g_pRasterizerState);
|
||||
ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||
ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||
ctx->RSSetState(bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Render function
|
||||
@@ -101,42 +122,43 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
|
||||
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
|
||||
return;
|
||||
}
|
||||
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
D3D11_BUFFER_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
||||
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||
@@ -148,16 +170,16 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
ctx->Unmap(g_pVB, 0);
|
||||
ctx->Unmap(g_pIB, 0);
|
||||
ctx->Unmap(bd->pVB, 0);
|
||||
ctx->Unmap(bd->pIB, 0);
|
||||
|
||||
// Setup orthographic projection matrix into our constant buffer
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||
return;
|
||||
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
|
||||
VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData;
|
||||
float L = draw_data->DisplayPos.x;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
@@ -170,7 +192,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||
ctx->Unmap(g_pVertexConstantBuffer, 0);
|
||||
ctx->Unmap(bd->pVertexConstantBuffer, 0);
|
||||
}
|
||||
|
||||
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||
@@ -232,7 +254,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != NULL)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
@@ -243,16 +265,22 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
|
||||
const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId;
|
||||
if (pcmd->TextureId != (ImTextureID)g_pFontTextureView)
|
||||
ctx->PSSetSamplers(0, 1, &g_pTextureSampler);
|
||||
else
|
||||
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
|
||||
if (pcmd->TextureId != (ImTextureID)bd->pFontTextureView)
|
||||
ctx->PSSetSamplers(0, 1, &bd->pTextureSampler);
|
||||
else
|
||||
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
@@ -285,6 +313,7 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
@@ -303,13 +332,13 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D11Texture2D* pTexture = NULL;
|
||||
ID3D11Texture2D* pTexture = nullptr;
|
||||
D3D11_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = pixels;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != NULL);
|
||||
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != nullptr);
|
||||
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
@@ -318,14 +347,15 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
||||
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
|
||||
pTexture->Release();
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)g_pFontTextureView);
|
||||
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
|
||||
|
||||
// Create texture samplers
|
||||
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||
{
|
||||
D3D11_SAMPLER_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
@@ -337,19 +367,20 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.MinLOD = 0.f;
|
||||
desc.MaxLOD = 0.f;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
|
||||
|
||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
|
||||
g_pd3dDevice->CreateSamplerState(&desc, &g_pTextureSampler);
|
||||
desc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
|
||||
desc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
|
||||
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTextureSampler);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return false;
|
||||
if (g_pFontSampler)
|
||||
if (bd->pFontSampler)
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||
@@ -389,9 +420,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
}";
|
||||
|
||||
ID3DBlob* vertexShaderBlob;
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
|
||||
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)
|
||||
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
@@ -404,7 +435,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
||||
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
|
||||
{
|
||||
vertexShaderBlob->Release();
|
||||
return false;
|
||||
@@ -414,12 +445,12 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
// Create the constant buffer
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
||||
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11);
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
||||
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,9 +473,9 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
}";
|
||||
|
||||
ID3DBlob* pixelShaderBlob;
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
|
||||
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
|
||||
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||
if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)
|
||||
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK)
|
||||
{
|
||||
pixelShaderBlob->Release();
|
||||
return false;
|
||||
@@ -465,7 +496,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
||||
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
|
||||
}
|
||||
|
||||
// Create the rasterizer state
|
||||
@@ -476,7 +507,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.CullMode = D3D11_CULL_NONE;
|
||||
desc.ScissorEnable = true;
|
||||
desc.DepthClipEnable = true;
|
||||
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
||||
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
|
||||
}
|
||||
|
||||
// Create depth-stencil State
|
||||
@@ -490,7 +521,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||
desc.BackFace = desc.FrontFace;
|
||||
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
||||
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_CreateFontsTexture();
|
||||
@@ -500,62 +531,81 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||
|
||||
void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||
{
|
||||
if (!g_pd3dDevice)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
if (!bd->pd3dDevice)
|
||||
return;
|
||||
|
||||
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
||||
if (g_pTextureSampler) { g_pTextureSampler->Release(); g_pTextureSampler = NULL; }
|
||||
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
||||
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
||||
|
||||
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
||||
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
||||
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
||||
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
||||
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
||||
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
|
||||
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
|
||||
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
|
||||
if (bd->pTextureSampler) { bd->pTextureSampler->Release(); bd->pTextureSampler = nullptr; }
|
||||
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
|
||||
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
|
||||
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
|
||||
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
|
||||
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
|
||||
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
||||
{
|
||||
// Setup backend capabilities flags
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx11";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
// Get factory from device
|
||||
IDXGIDevice* pDXGIDevice = NULL;
|
||||
IDXGIAdapter* pDXGIAdapter = NULL;
|
||||
IDXGIFactory* pFactory = NULL;
|
||||
IDXGIDevice* pDXGIDevice = nullptr;
|
||||
IDXGIAdapter* pDXGIAdapter = nullptr;
|
||||
IDXGIFactory* pFactory = nullptr;
|
||||
|
||||
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
||||
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
||||
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
||||
{
|
||||
g_pd3dDevice = device;
|
||||
g_pd3dDeviceContext = device_context;
|
||||
g_pFactory = pFactory;
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDeviceContext = device_context;
|
||||
bd->pFactory = pFactory;
|
||||
}
|
||||
if (pDXGIDevice) pDXGIDevice->Release();
|
||||
if (pDXGIAdapter) pDXGIAdapter->Release();
|
||||
g_pd3dDevice->AddRef();
|
||||
g_pd3dDeviceContext->AddRef();
|
||||
bd->pd3dDevice->AddRef();
|
||||
bd->pd3dDeviceContext->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
|
||||
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
||||
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
|
||||
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplDX11_NewFrame()
|
||||
{
|
||||
if (!g_pFontSampler)
|
||||
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?");
|
||||
|
||||
if (!bd->pFontSampler)
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "imgui/imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
@@ -24,3 +25,5 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -0,0 +1,368 @@
|
||||
// dear imgui: Renderer Backend for DirectX9
|
||||
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
|
||||
// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
|
||||
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
|
||||
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
|
||||
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||
// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
|
||||
// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
|
||||
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
||||
// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
|
||||
// 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||
// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_dx9.h"
|
||||
|
||||
// DirectX
|
||||
#include <d3d9.h>
|
||||
|
||||
// DirectX data
|
||||
struct ImGui_ImplDX9_Data
|
||||
{
|
||||
LPDIRECT3DDEVICE9 pd3dDevice;
|
||||
LPDIRECT3DVERTEXBUFFER9 pVB;
|
||||
LPDIRECT3DINDEXBUFFER9 pIB;
|
||||
LPDIRECT3DTEXTURE9 FontTexture;
|
||||
int VertexBufferSize;
|
||||
int IndexBufferSize;
|
||||
|
||||
ImGui_ImplDX9_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||
};
|
||||
|
||||
struct CUSTOMVERTEX
|
||||
{
|
||||
float pos[3];
|
||||
D3DCOLOR col;
|
||||
float uv[2];
|
||||
};
|
||||
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
|
||||
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL)
|
||||
#else
|
||||
#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
|
||||
#endif
|
||||
|
||||
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||
static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
// Functions
|
||||
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
|
||||
// Setup viewport
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = vp.Y = 0;
|
||||
vp.Width = (DWORD)draw_data->DisplaySize.x;
|
||||
vp.Height = (DWORD)draw_data->DisplaySize.y;
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
bd->pd3dDevice->SetViewport(&vp);
|
||||
|
||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient), bilinear sampling.
|
||||
bd->pd3dDevice->SetPixelShader(nullptr);
|
||||
bd->pd3dDevice->SetVertexShader(nullptr);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
bd->pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
|
||||
bd->pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
bd->pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||
// Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
|
||||
{
|
||||
float L = draw_data->DisplayPos.x + 0.5f;
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
|
||||
float T = draw_data->DisplayPos.y + 0.5f;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
|
||||
D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
|
||||
D3DMATRIX mat_projection =
|
||||
{ { {
|
||||
2.0f/(R-L), 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 2.0f/(T-B), 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
|
||||
} } };
|
||||
bd->pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
|
||||
}
|
||||
}
|
||||
|
||||
// Render function.
|
||||
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
// Create and grow buffers if needed
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
if (bd->pd3dDevice->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate buffers
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
bd->pVB->Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
|
||||
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
|
||||
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
|
||||
for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
|
||||
{
|
||||
vtx_dst->pos[0] = vtx_src->pos.x;
|
||||
vtx_dst->pos[1] = vtx_src->pos.y;
|
||||
vtx_dst->pos[2] = 0.0f;
|
||||
vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col);
|
||||
vtx_dst->uv[0] = vtx_src->uv.x;
|
||||
vtx_dst->uv[1] = vtx_src->uv.y;
|
||||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
bd->pVB->Unlock();
|
||||
bd->pIB->Unlock();
|
||||
bd->pd3dDevice->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
|
||||
bd->pd3dDevice->SetIndices(bd->pIB);
|
||||
bd->pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
|
||||
|
||||
// Setup desired DX state
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
|
||||
// Render command lists
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||
ImGui_ImplDX9_SetupRenderState(draw_data);
|
||||
else
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply Scissor/clipping rectangle, Bind texture, Draw
|
||||
const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
|
||||
bd->pd3dDevice->SetTexture(0, texture);
|
||||
if (texture != bd->FontTexture)
|
||||
{
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
|
||||
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
|
||||
}
|
||||
bd->pd3dDevice->SetScissorRect(&r);
|
||||
bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
|
||||
}
|
||||
}
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_dx9";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
bd->pd3dDevice = device;
|
||||
bd->pd3dDevice->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
static bool ImGui_ImplDX9_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
unsigned char* pixels;
|
||||
int width, height, bytes_per_pixel;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
|
||||
|
||||
// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
|
||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
if (io.Fonts->TexPixelsUseColors)
|
||||
{
|
||||
ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel);
|
||||
for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++)
|
||||
*dst = IMGUI_COL_TO_DX9_ARGB(*src);
|
||||
pixels = (unsigned char*)dst_start;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Upload texture to graphics system
|
||||
bd->FontTexture = nullptr;
|
||||
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
|
||||
return false;
|
||||
D3DLOCKED_RECT tex_locked_rect;
|
||||
if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
|
||||
return false;
|
||||
for (int y = 0; y < height; y++)
|
||||
memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel);
|
||||
bd->FontTexture->UnlockRect(0);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
|
||||
|
||||
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
|
||||
if (io.Fonts->TexPixelsUseColors)
|
||||
ImGui::MemFree(pixels);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return false;
|
||||
if (!ImGui_ImplDX9_CreateFontsTexture())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_InvalidateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
if (!bd || !bd->pd3dDevice)
|
||||
return;
|
||||
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_NewFrame()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX9_Init()?");
|
||||
|
||||
if (!bd->FontTexture)
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -3,14 +3,16 @@
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#pragma once
|
||||
#include "imgui/imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct IDirect3DDevice9;
|
||||
|
||||
@@ -22,3 +24,5 @@ IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
+23
-21
@@ -67,13 +67,13 @@
|
||||
#endif
|
||||
|
||||
#include "wsi/gl_context.h"
|
||||
#include "glcache.h"
|
||||
#include "rend/gles/glcache.h"
|
||||
#include "hw/pvr/Renderer_if.h"
|
||||
|
||||
// OpenGL Data
|
||||
static char g_GlslVersionString[32] = "";
|
||||
static GLuint g_FontTexture = 0;
|
||||
static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
||||
static GLuint g_ShaderHandle = 0;
|
||||
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
|
||||
@@ -145,7 +145,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||
glcache.Enable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glcache.Disable(GL_CULL_FACE);
|
||||
glcache.Disable(GL_DEPTH_TEST);
|
||||
glcache.Enable(GL_SCISSOR_TEST);
|
||||
@@ -187,6 +187,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
}
|
||||
#endif
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||
@@ -199,12 +200,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
@@ -228,12 +225,14 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
// Bind texture, Draw
|
||||
glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
|
||||
}
|
||||
}
|
||||
idx_buffer_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
// Make sure the state cache is coherent
|
||||
glcache.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
#ifndef GLES2
|
||||
if (vao_handle != 0)
|
||||
glDeleteVertexArrays(1, &vao_handle);
|
||||
@@ -442,23 +441,28 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects()
|
||||
|
||||
// Create shaders
|
||||
const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader };
|
||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
|
||||
glCompileShader(g_VertHandle);
|
||||
CheckShader(g_VertHandle, "vertex shader");
|
||||
GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL);
|
||||
glCompileShader(vert_handle);
|
||||
CheckShader(vert_handle, "vertex shader");
|
||||
|
||||
const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader };
|
||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
|
||||
glCompileShader(g_FragHandle);
|
||||
CheckShader(g_FragHandle, "fragment shader");
|
||||
GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL);
|
||||
glCompileShader(frag_handle);
|
||||
CheckShader(frag_handle, "fragment shader");
|
||||
|
||||
g_ShaderHandle = glCreateProgram();
|
||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||
glAttachShader(g_ShaderHandle, vert_handle);
|
||||
glAttachShader(g_ShaderHandle, frag_handle);
|
||||
glLinkProgram(g_ShaderHandle);
|
||||
CheckProgram(g_ShaderHandle, "shader program");
|
||||
|
||||
glDetachShader(g_ShaderHandle, vert_handle);
|
||||
glDetachShader(g_ShaderHandle, frag_handle);
|
||||
glDeleteShader(vert_handle);
|
||||
glDeleteShader(frag_handle);
|
||||
|
||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||
@@ -481,8 +485,6 @@ static void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
||||
g_VboHandle = g_ElementsHandle = 0;
|
||||
|
||||
glcache.DeleteProgram(g_ShaderHandle);
|
||||
g_VertHandle = 0;
|
||||
g_FragHandle = 0;
|
||||
g_ShaderHandle = 0;
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||
File renamed without changes.
+149
-108
@@ -2,8 +2,8 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
|
||||
// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
|
||||
@@ -30,6 +30,11 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2023-07-04: Vulkan: Added optional support for VK_KHR_dynamic_rendering. User needs to set init_info->UseDynamicRendering = true and init_info->ColorAttachmentFormat.
|
||||
// 2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not being honored + removed a bunch of duplicate code.
|
||||
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#914, #5738).
|
||||
// 2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires '#define ImTextureID ImU64'. (#914).
|
||||
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
|
||||
@@ -61,6 +66,8 @@
|
||||
// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.
|
||||
// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_vulkan.h"
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -113,7 +120,7 @@ struct ImGui_ImplVulkan_Data
|
||||
VkDeviceMemory UploadBufferMemory;
|
||||
VkBuffer UploadBuffer;
|
||||
|
||||
// Render buffers
|
||||
// Render buffers for main window
|
||||
ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers;
|
||||
|
||||
ImGui_ImplVulkan_Data()
|
||||
@@ -189,6 +196,7 @@ static bool g_FunctionsLoaded = true;
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeDescriptorSets) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \
|
||||
IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \
|
||||
@@ -207,6 +215,12 @@ IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
|
||||
#undef IMGUI_VULKAN_FUNC_DEF
|
||||
#endif // VK_NO_PROTOTYPES
|
||||
|
||||
#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering)
|
||||
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR;
|
||||
static PFN_vkCmdEndRenderingKHR ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SHADERS
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -219,8 +233,10 @@ layout(location = 0) in vec2 aPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
layout(location = 2) in vec4 aColor;
|
||||
layout(push_constant) uniform uPushConstant { vec2 uScale; vec2 uTranslate; } pc;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
layout(location = 0) out struct { vec4 Color; vec2 UV; } Out;
|
||||
|
||||
void main()
|
||||
{
|
||||
Out.Color = aColor;
|
||||
@@ -323,7 +339,7 @@ static uint32_t __glsl_shader_frag_spv[] =
|
||||
// FIXME: multi-context support is not tested and probably dysfunctional in this backend.
|
||||
static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
|
||||
return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||
}
|
||||
|
||||
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
|
||||
@@ -442,7 +458,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
|
||||
// Allocate array to store enough vertex/index buffers
|
||||
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers;
|
||||
if (wrb->FrameRenderBuffers == NULL)
|
||||
if (wrb->FrameRenderBuffers == nullptr)
|
||||
{
|
||||
wrb->Index = 0;
|
||||
wrb->Count = v->ImageCount;
|
||||
@@ -469,8 +485,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
CreateOrResizeBuffer(rb->IndexBuffer, rb->IndexBufferMemory, rb->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
ImDrawVert* vtx_dst = NULL;
|
||||
ImDrawIdx* idx_dst = NULL;
|
||||
ImDrawVert* vtx_dst = nullptr;
|
||||
ImDrawIdx* idx_dst = nullptr;
|
||||
VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst));
|
||||
check_vk_result(err);
|
||||
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst));
|
||||
@@ -513,7 +529,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback != NULL)
|
||||
if (pcmd->UserCallback != nullptr)
|
||||
{
|
||||
// User callback, registered via ImDrawList::AddCallback()
|
||||
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||
@@ -552,7 +568,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->FontDescriptorSet);
|
||||
desc_set[0] = bd->FontDescriptorSet;
|
||||
}
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, NULL);
|
||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, nullptr);
|
||||
|
||||
// Draw
|
||||
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
|
||||
@@ -565,7 +581,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
// Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
|
||||
// Our last values will leak into user/application rendering IF:
|
||||
// - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
|
||||
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
|
||||
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitly set that state.
|
||||
// If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
|
||||
// In theory we should aim to backup/restore those values but I am not sure this is possible.
|
||||
// We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
|
||||
@@ -657,7 +673,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
|
||||
// Upload to Buffer:
|
||||
{
|
||||
char* map = NULL;
|
||||
char* map = nullptr;
|
||||
err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
|
||||
check_vk_result(err);
|
||||
memcpy(map, pixels, upload_size);
|
||||
@@ -683,7 +699,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
copy_barrier[0].subresourceRange.levelCount = 1;
|
||||
copy_barrier[0].subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier);
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
@@ -705,7 +721,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
use_barrier[0].subresourceRange.levelCount = 1;
|
||||
use_barrier[0].subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier);
|
||||
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
|
||||
}
|
||||
|
||||
// Store our identifier
|
||||
@@ -738,69 +754,6 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAlloca
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
if (bd->FontSampler)
|
||||
return;
|
||||
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
VkSamplerCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
info.magFilter = VK_FILTER_LINEAR;
|
||||
info.minFilter = VK_FILTER_LINEAR;
|
||||
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.minLod = -1000;
|
||||
info.maxLod = 1000;
|
||||
info.maxAnisotropy = 1.0f;
|
||||
VkResult err = vkCreateSampler(device, &info, allocator, &bd->FontSampler);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
if (bd->DescriptorSetLayout)
|
||||
return;
|
||||
|
||||
VkDescriptorSetLayoutBinding binding[1] = {};
|
||||
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
binding[0].descriptorCount = 1;
|
||||
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
VkDescriptorSetLayoutCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = binding;
|
||||
VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &bd->DescriptorSetLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
if (bd->PipelineLayout)
|
||||
return;
|
||||
|
||||
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
|
||||
ImGui_ImplVulkan_CreateDescriptorSetLayout(device, allocator);
|
||||
VkPushConstantRange push_constants[1] = {};
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
push_constants[0].offset = sizeof(float) * 0;
|
||||
push_constants[0].size = sizeof(float) * 4;
|
||||
VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
|
||||
VkPipelineLayoutCreateInfo layout_info = {};
|
||||
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants;
|
||||
VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &bd->PipelineLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
@@ -885,8 +838,6 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
|
||||
dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states);
|
||||
dynamic_state.pDynamicStates = dynamic_states;
|
||||
|
||||
ImGui_ImplVulkan_CreatePipelineLayout(device, allocator);
|
||||
|
||||
VkGraphicsPipelineCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
info.flags = bd->PipelineCreateFlags;
|
||||
@@ -903,6 +854,19 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
|
||||
info.layout = bd->PipelineLayout;
|
||||
info.renderPass = renderPass;
|
||||
info.subpass = subpass;
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {};
|
||||
pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR;
|
||||
pipelineRenderingCreateInfo.colorAttachmentCount = 1;
|
||||
pipelineRenderingCreateInfo.pColorAttachmentFormats = &bd->VulkanInitInfo.ColorAttachmentFormat;
|
||||
if (bd->VulkanInitInfo.UseDynamicRendering)
|
||||
{
|
||||
info.pNext = &pipelineRenderingCreateInfo;
|
||||
info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
|
||||
}
|
||||
#endif
|
||||
|
||||
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
|
||||
check_vk_result(err);
|
||||
}
|
||||
@@ -911,10 +875,58 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
VkResult err;
|
||||
|
||||
if (!bd->FontSampler)
|
||||
{
|
||||
// Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
|
||||
VkSamplerCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
info.magFilter = VK_FILTER_LINEAR;
|
||||
info.minFilter = VK_FILTER_LINEAR;
|
||||
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
info.minLod = -1000;
|
||||
info.maxLod = 1000;
|
||||
info.maxAnisotropy = 1.0f;
|
||||
err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
if (!bd->DescriptorSetLayout)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding binding[1] = {};
|
||||
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
binding[0].descriptorCount = 1;
|
||||
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
VkDescriptorSetLayoutCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = binding;
|
||||
err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
if (!bd->PipelineLayout)
|
||||
{
|
||||
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
|
||||
VkPushConstantRange push_constants[1] = {};
|
||||
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
push_constants[0].offset = sizeof(float) * 0;
|
||||
push_constants[0].size = sizeof(float) * 4;
|
||||
VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
|
||||
VkPipelineLayoutCreateInfo layout_info = {};
|
||||
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_info.setLayoutCount = 1;
|
||||
layout_info.pSetLayouts = set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants;
|
||||
err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd->PipelineLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
ImGui_ImplVulkan_CreateFontSampler(v->Device, v->Allocator);
|
||||
ImGui_ImplVulkan_CreateDescriptorSetLayout(v->Device, v->Allocator);
|
||||
ImGui_ImplVulkan_CreatePipelineLayout(v->Device, v->Allocator);
|
||||
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass);
|
||||
|
||||
return true;
|
||||
@@ -946,19 +958,12 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
|
||||
if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
|
||||
if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
|
||||
if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
|
||||
if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; ImGui::GetIO().Fonts->SetTexID(ImTextureID()); }
|
||||
if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; ImGui::GetIO().Fonts->SetTexID(ImTextureID()); }
|
||||
if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }
|
||||
if (bd->FontSampler) { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; }
|
||||
if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
|
||||
if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
|
||||
if (bd->Pipeline)
|
||||
{
|
||||
// Avoid destroying the in-flight pipeline
|
||||
vkDeviceWaitIdle(v->Device);
|
||||
vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator);
|
||||
bd->Pipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
bd->FontDescriptorSet = VK_NULL_HANDLE;
|
||||
if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
|
||||
@@ -970,14 +975,21 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
|
||||
#ifdef VK_NO_PROTOTYPES
|
||||
#define IMGUI_VULKAN_FUNC_LOAD(func) \
|
||||
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
|
||||
if (func == NULL) \
|
||||
if (func == nullptr) \
|
||||
return false;
|
||||
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)
|
||||
#undef IMGUI_VULKAN_FUNC_LOAD
|
||||
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
// Manually load those two (see #5446)
|
||||
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func("vkCmdBeginRenderingKHR", user_data));
|
||||
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func("vkCmdEndRenderingKHR", user_data));
|
||||
#endif
|
||||
#else
|
||||
IM_UNUSED(loader_func);
|
||||
IM_UNUSED(user_data);
|
||||
#endif
|
||||
|
||||
g_FunctionsLoaded = true;
|
||||
return true;
|
||||
}
|
||||
@@ -986,8 +998,22 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
|
||||
{
|
||||
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
|
||||
|
||||
if (info->UseDynamicRendering)
|
||||
{
|
||||
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(vkGetInstanceProcAddr(info->Instance, "vkCmdBeginRenderingKHR"));
|
||||
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(vkGetInstanceProcAddr(info->Instance, "vkCmdEndRenderingKHR"));
|
||||
#endif
|
||||
IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr);
|
||||
IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr);
|
||||
#else
|
||||
IM_ASSERT(0 && "Can't use dynamic rendering when neither VK_VERSION_1_3 or VK_KHR_dynamic_rendering is defined.");
|
||||
#endif
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
|
||||
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||
|
||||
// Setup backend capabilities flags
|
||||
ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();
|
||||
@@ -1002,7 +1028,8 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
|
||||
IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->MinImageCount >= 2);
|
||||
IM_ASSERT(info->ImageCount >= info->MinImageCount);
|
||||
IM_ASSERT(render_pass != VK_NULL_HANDLE);
|
||||
if (info->UseDynamicRendering == false)
|
||||
IM_ASSERT(render_pass != VK_NULL_HANDLE);
|
||||
|
||||
bd->VulkanInitInfo = *info;
|
||||
bd->RenderPass = render_pass;
|
||||
@@ -1016,19 +1043,20 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
|
||||
void ImGui_ImplVulkan_Shutdown()
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
|
||||
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui_ImplVulkan_DestroyDeviceObjects();
|
||||
io.BackendRendererName = NULL;
|
||||
io.BackendRendererUserData = NULL;
|
||||
io.BackendRendererName = nullptr;
|
||||
io.BackendRendererUserData = nullptr;
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_NewFrame()
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplVulkan_Init()?");
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?");
|
||||
IM_UNUSED(bd);
|
||||
}
|
||||
|
||||
@@ -1077,11 +1105,18 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
|
||||
write_desc[0].descriptorCount = 1;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write_desc[0].pImageInfo = desc_image;
|
||||
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
|
||||
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, nullptr);
|
||||
}
|
||||
return descriptor_set;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
|
||||
{
|
||||
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
|
||||
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
|
||||
vkFreeDescriptorSets(v->Device, v->DescriptorPool, 1, &descriptor_set);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
|
||||
@@ -1101,7 +1136,7 @@ VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image
|
||||
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
|
||||
{
|
||||
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
|
||||
IM_ASSERT(request_formats != NULL);
|
||||
IM_ASSERT(request_formats != nullptr);
|
||||
IM_ASSERT(request_formats_count > 0);
|
||||
|
||||
// Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
|
||||
@@ -1109,7 +1144,7 @@ VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physic
|
||||
// Additionally several new color spaces were introduced with Vulkan Spec v1.0.40,
|
||||
// hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.
|
||||
uint32_t avail_count;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, NULL);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, nullptr);
|
||||
ImVector<VkSurfaceFormatKHR> avail_format;
|
||||
avail_format.resize((int)avail_count);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data);
|
||||
@@ -1146,12 +1181,12 @@ VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physic
|
||||
VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
|
||||
{
|
||||
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
|
||||
IM_ASSERT(request_modes != NULL);
|
||||
IM_ASSERT(request_modes != nullptr);
|
||||
IM_ASSERT(request_modes_count > 0);
|
||||
|
||||
// Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
|
||||
uint32_t avail_count = 0;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, NULL);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, nullptr);
|
||||
ImVector<VkPresentModeKHR> avail_modes;
|
||||
avail_modes.resize((int)avail_count);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data);
|
||||
@@ -1243,8 +1278,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
}
|
||||
IM_FREE(wd->Frames);
|
||||
IM_FREE(wd->FrameSemaphores);
|
||||
wd->Frames = NULL;
|
||||
wd->FrameSemaphores = NULL;
|
||||
wd->Frames = nullptr;
|
||||
wd->FrameSemaphores = nullptr;
|
||||
wd->ImageCount = 0;
|
||||
if (wd->RenderPass)
|
||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||
@@ -1291,7 +1326,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
}
|
||||
err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
|
||||
check_vk_result(err);
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL);
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, nullptr);
|
||||
check_vk_result(err);
|
||||
VkImage backbuffers[16] = {};
|
||||
IM_ASSERT(wd->ImageCount >= min_image_count);
|
||||
@@ -1299,7 +1334,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
|
||||
check_vk_result(err);
|
||||
|
||||
IM_ASSERT(wd->Frames == NULL);
|
||||
IM_ASSERT(wd->Frames == nullptr);
|
||||
wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
|
||||
wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);
|
||||
memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
|
||||
@@ -1311,6 +1346,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
vkDestroySwapchainKHR(device, old_swapchain, allocator);
|
||||
|
||||
// Create the Render Pass
|
||||
if (wd->UseDynamicRendering == false)
|
||||
{
|
||||
VkAttachmentDescription attachment = {};
|
||||
attachment.format = wd->SurfaceFormat.format;
|
||||
@@ -1373,6 +1409,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
|
||||
}
|
||||
|
||||
// Create Framebuffer
|
||||
if (wd->UseDynamicRendering == false)
|
||||
{
|
||||
VkImageView attachment[1];
|
||||
VkFramebufferCreateInfo info = {};
|
||||
@@ -1414,8 +1451,8 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui
|
||||
}
|
||||
IM_FREE(wd->Frames);
|
||||
IM_FREE(wd->FrameSemaphores);
|
||||
wd->Frames = NULL;
|
||||
wd->FrameSemaphores = NULL;
|
||||
wd->Frames = nullptr;
|
||||
wd->FrameSemaphores = nullptr;
|
||||
vkDestroyPipeline(device, wd->Pipeline, allocator);
|
||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
|
||||
@@ -1459,7 +1496,11 @@ void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVul
|
||||
for (uint32_t n = 0; n < buffers->Count; n++)
|
||||
ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
|
||||
IM_FREE(buffers->FrameRenderBuffers);
|
||||
buffers->FrameRenderBuffers = NULL;
|
||||
buffers->FrameRenderBuffers = nullptr;
|
||||
buffers->Index = 0;
|
||||
buffers->Count = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
+17
-5
@@ -2,8 +2,8 @@
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
|
||||
// See imgui_impl_vulkan.cpp file for details.
|
||||
@@ -24,6 +24,7 @@
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
#pragma once
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui/imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
// [Configuration] in order to use a custom Vulkan function loader:
|
||||
@@ -59,6 +60,12 @@ struct ImGui_ImplVulkan_InitInfo
|
||||
uint32_t MinImageCount; // >= 2
|
||||
uint32_t ImageCount; // >= MinImageCount
|
||||
VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT (0 -> default to VK_SAMPLE_COUNT_1_BIT)
|
||||
|
||||
// Dynamic Rendering (Optional)
|
||||
bool UseDynamicRendering; // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
|
||||
VkFormat ColorAttachmentFormat; // Required for dynamic rendering
|
||||
|
||||
// Allocation, Debugging
|
||||
const VkAllocationCallbacks* Allocator;
|
||||
void (*CheckVkResultFn)(VkResult err);
|
||||
};
|
||||
@@ -73,12 +80,14 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
|
||||
|
||||
// Register a texture (VkDescriptorSet == ImTextureID)
|
||||
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
|
||||
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem
|
||||
// Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
|
||||
IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
|
||||
|
||||
// Optional: load Vulkan functions with a custom function loader
|
||||
// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = NULL);
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
@@ -87,8 +96,8 @@ IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*l
|
||||
// You probably do NOT need to use or care about those functions.
|
||||
// Those functions only exist because:
|
||||
// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
|
||||
// 2) the upcoming multi-viewport feature will need them internally.
|
||||
// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
|
||||
// 2) the multi-viewport / platform window implementation needs them internally.
|
||||
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
|
||||
// but it is too much code to duplicate everywhere so we exceptionally expose them.
|
||||
//
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
@@ -137,6 +146,7 @@ struct ImGui_ImplVulkanH_Window
|
||||
VkPresentModeKHR PresentMode;
|
||||
VkRenderPass RenderPass;
|
||||
VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
|
||||
bool UseDynamicRendering;
|
||||
bool ClearEnable;
|
||||
VkClearValue ClearValue;
|
||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
||||
@@ -152,3 +162,5 @@ struct ImGui_ImplVulkanH_Window
|
||||
ClearEnable = true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
+49
-37
@@ -1,5 +1,5 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -9,7 +9,7 @@
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
@@ -20,28 +20,34 @@
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
||||
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows.
|
||||
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
|
||||
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
@@ -53,27 +59,46 @@
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of imgui cpp files.
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||
|
||||
//---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library.
|
||||
// Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
||||
// #define IMGUI_USE_STB_SPRINTF
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
//#define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
|
||||
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
@@ -87,31 +112,18 @@
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger
|
||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
|
||||
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
|
||||
// This adds a small runtime cost which is why it is not enabled by default.
|
||||
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, const MyMatrix44& v);
|
||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOG_TAG "flycast"
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
+6839
-2837
File diff suppressed because it is too large.
Load diff
+1290
-549
File diff suppressed because it is too large.
Load diff
+4257
-1715
File diff suppressed because it is too large.
Load diff
+854
-420
File diff suppressed because it is too large.
Load diff
+1741
-554
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+2075
-1743
File diff suppressed because it is too large.
Load diff
@@ -1,15 +1,19 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.00.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Added STBRP__CDECL
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
|
||||
//
|
||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Before #including,
|
||||
//
|
||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||
//
|
||||
// in the file that you want to have the implementation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
@@ -34,13 +38,14 @@
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// github:IntellectualKitty
|
||||
//
|
||||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
@@ -81,11 +86,10 @@ typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
typedef int stbrp_coord;
|
||||
#else
|
||||
typedef unsigned short stbrp_coord;
|
||||
#endif
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
@@ -213,10 +217,9 @@ struct stbrp_context
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
// [DEAR IMGUI] Added STBRP__CDECL
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#define STBRP__CDECL __cdecl
|
||||
#define STBRP__CDECL __cdecl
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#define STBRP__CDECL
|
||||
@@ -262,9 +265,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
#ifndef STBRP_LARGE_RECTS
|
||||
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||
#endif
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
@@ -283,11 +283,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
context->extra[1].y = (1<<30);
|
||||
#else
|
||||
context->extra[1].y = 65535;
|
||||
#endif
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
@@ -433,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
STBRP_ASSERT(y <= best_y);
|
||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
@@ -441,7 +437,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||
}
|
||||
}
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fr.prev_link = best;
|
||||
@@ -529,7 +525,6 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
|
||||
return res;
|
||||
}
|
||||
|
||||
// [DEAR IMGUI] Added STBRP__CDECL
|
||||
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
@@ -541,7 +536,6 @@ static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
// [DEAR IMGUI] Added STBRP__CDECL
|
||||
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
@@ -549,12 +543,6 @@ static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
#ifdef STBRP_LARGE_RECTS
|
||||
#define STBRP__MAXVAL 0xffffffff
|
||||
#else
|
||||
#define STBRP__MAXVAL 0xffff
|
||||
#endif
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
@@ -602,38 +590,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
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 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
|
||||
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 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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1,10 +1,11 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_textedit.h 1.13.
|
||||
// This is a slightly modified version of stb_textedit.h 1.14.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000)
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_textedit.h - v1.13 - public domain - Sean Barrett
|
||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||
// Development of this library was sponsored by RAD Game Tools
|
||||
//
|
||||
// This C header file implements the guts of a multi-line text-editing
|
||||
@@ -19,7 +20,7 @@
|
||||
// texts, as its performance does not scale and it has limited undo).
|
||||
//
|
||||
// Non-trivial behaviors are modelled after Windows text controls.
|
||||
//
|
||||
//
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
@@ -35,6 +36,7 @@
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 1.14 (2021-07-11) page up/down, various fixes
|
||||
// 1.13 (2019-02-07) fix bug in undo size management
|
||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
||||
@@ -58,6 +60,7 @@
|
||||
// Ulf Winklemann: move-by-word in 1.1
|
||||
// Fabian Giesen: secondary key inputs in 1.5
|
||||
// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
|
||||
// Louis Schnellbach: page up/down in 1.14
|
||||
//
|
||||
// Bugfixes:
|
||||
// Scott Graham
|
||||
@@ -93,8 +96,8 @@
|
||||
// moderate sizes. The undo system does no memory allocations, so
|
||||
// it grows STB_TexteditState by the worst-case storage which is (in bytes):
|
||||
//
|
||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
|
||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
|
||||
// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT
|
||||
// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT
|
||||
//
|
||||
//
|
||||
// Implementation mode:
|
||||
@@ -217,20 +220,20 @@
|
||||
// call this with the mouse x,y on a mouse down; it will update the cursor
|
||||
// and reset the selection start/end to the cursor point. the x,y must
|
||||
// be relative to the text widget, with (0,0) being the top left.
|
||||
//
|
||||
//
|
||||
// drag:
|
||||
// call this with the mouse x,y on a mouse drag/up; it will update the
|
||||
// cursor and the selection end point
|
||||
//
|
||||
//
|
||||
// cut:
|
||||
// call this to delete the current selection; returns true if there was
|
||||
// one. you should FIRST copy the current selection to the system paste buffer.
|
||||
// (To copy, just copy the current selection out of the string yourself.)
|
||||
//
|
||||
//
|
||||
// paste:
|
||||
// call this to paste text at the current cursor point or over the current
|
||||
// selection if there is one.
|
||||
//
|
||||
//
|
||||
// key:
|
||||
// call this for keyboard inputs sent to the textfield. you can use it
|
||||
// for "key down" events or for "translated" key events. if you need to
|
||||
@@ -241,7 +244,7 @@
|
||||
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
||||
// anything other type you wante before including.
|
||||
//
|
||||
//
|
||||
//
|
||||
// When rendering, you can read the cursor position and selection state from
|
||||
// the STB_TexteditState.
|
||||
//
|
||||
@@ -522,29 +525,14 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
||||
int z = STB_TEXTEDIT_STRINGLEN(str);
|
||||
int i=0, first;
|
||||
|
||||
if (n == z) {
|
||||
// if it's at the end, then find the last line -- simpler than trying to
|
||||
// explicitly handle this case in the regular code
|
||||
if (single_line) {
|
||||
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
|
||||
find->y = 0;
|
||||
find->first_char = 0;
|
||||
find->length = z;
|
||||
find->height = r.ymax - r.ymin;
|
||||
find->x = r.x1;
|
||||
} else {
|
||||
find->y = 0;
|
||||
find->x = 0;
|
||||
find->height = 1;
|
||||
while (i < z) {
|
||||
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||
prev_start = i;
|
||||
i += r.num_chars;
|
||||
}
|
||||
find->first_char = i;
|
||||
find->length = 0;
|
||||
find->prev_first = prev_start;
|
||||
}
|
||||
if (n == z && single_line) {
|
||||
// special case if it's at the end (may not be needed?)
|
||||
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
|
||||
find->y = 0;
|
||||
find->first_char = 0;
|
||||
find->length = z;
|
||||
find->height = r.ymax - r.ymin;
|
||||
find->x = r.x1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -555,9 +543,13 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
||||
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
|
||||
if (n < i + r.num_chars)
|
||||
break;
|
||||
if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line
|
||||
break; // [DEAR IMGUI]
|
||||
prev_start = i;
|
||||
i += r.num_chars;
|
||||
find->y += r.baseline_y_delta;
|
||||
if (i == z) // [DEAR IMGUI]
|
||||
break; // [DEAR IMGUI]
|
||||
}
|
||||
|
||||
find->first_char = first = i;
|
||||
@@ -716,9 +708,7 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
|
||||
state->has_preferred_x = 0;
|
||||
return 1;
|
||||
}
|
||||
// remove the undo since we didn't actually insert the characters
|
||||
if (state->undostate.undo_point)
|
||||
--state->undostate.undo_point;
|
||||
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -764,7 +754,7 @@ retry:
|
||||
state->insert_mode = !state->insert_mode;
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
case STB_TEXTEDIT_K_UNDO:
|
||||
stb_text_undo(str, state);
|
||||
state->has_preferred_x = 0;
|
||||
@@ -779,7 +769,7 @@ retry:
|
||||
// if currently there's a selection, move cursor to start of selection
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_first(state);
|
||||
else
|
||||
else
|
||||
if (state->cursor > 0)
|
||||
--state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
@@ -828,7 +818,7 @@ retry:
|
||||
|
||||
#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
|
||||
case STB_TEXTEDIT_K_WORDRIGHT:
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_last(str, state);
|
||||
else {
|
||||
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
|
||||
@@ -922,7 +912,7 @@ retry:
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case STB_TEXTEDIT_K_UP:
|
||||
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
|
||||
case STB_TEXTEDIT_K_PGUP:
|
||||
@@ -1014,7 +1004,7 @@ retry:
|
||||
}
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_TEXTSTART2
|
||||
case STB_TEXTEDIT_K_TEXTSTART2:
|
||||
#endif
|
||||
@@ -1031,7 +1021,7 @@ retry:
|
||||
state->select_start = state->select_end = 0;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
|
||||
#ifdef STB_TEXTEDIT_K_TEXTSTART2
|
||||
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
|
||||
#endif
|
||||
@@ -1410,38 +1400,38 @@ This software is available under 2 licenses -- choose whichever you prefer.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
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 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
|
||||
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 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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
+535
-353
File diff suppressed because it is too large.
Load diff
+291
-253
File diff suppressed because it is too large.
Load diff
+38
-38
@@ -1,6 +1,6 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2022 Evan Pezent
|
||||
// Copyright (c) 2023 Evan Pezent
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -20,7 +20,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// ImPlot v0.14
|
||||
// ImPlot v0.16
|
||||
|
||||
// Table of Contents:
|
||||
//
|
||||
@@ -60,7 +60,7 @@
|
||||
#endif
|
||||
|
||||
// ImPlot version string.
|
||||
#define IMPLOT_VERSION "0.14"
|
||||
#define IMPLOT_VERSION "0.16"
|
||||
// Indicates variable should deduced automatically.
|
||||
#define IMPLOT_AUTO -1
|
||||
// Special color used to indicate that a color should be deduced automatically.
|
||||
@@ -145,7 +145,7 @@ enum ImPlotFlags_ {
|
||||
// Options for plot axes (see SetupAxis).
|
||||
enum ImPlotAxisFlags_ {
|
||||
ImPlotAxisFlags_None = 0, // default
|
||||
ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is NULL)
|
||||
ImPlotAxisFlags_NoLabel = 1 << 0, // the axis label will not be displayed (axis labels are also hidden if the supplied string name is nullptr)
|
||||
ImPlotAxisFlags_NoGridLines = 1 << 1, // no grid lines will be displayed
|
||||
ImPlotAxisFlags_NoTickMarks = 1 << 2, // no tick marks will be displayed
|
||||
ImPlotAxisFlags_NoTickLabels = 1 << 3, // no text labels will be displayed
|
||||
@@ -468,7 +468,7 @@ struct ImPlotPoint {
|
||||
double x, y;
|
||||
ImPlotPoint() { x = y = 0.0; }
|
||||
ImPlotPoint(double _x, double _y) { x = _x; y = _y; }
|
||||
ImPlotPoint(const ImVec2& p) { x = p.x; y = p.y; }
|
||||
ImPlotPoint(const ImVec2& p) { x = (double)p.x; y = (double)p.y; }
|
||||
double operator[] (size_t idx) const { return (&x)[idx]; }
|
||||
double& operator[] (size_t idx) { return (&x)[idx]; }
|
||||
#ifdef IMPLOT_POINT_CLASS_EXTRA
|
||||
@@ -596,9 +596,9 @@ namespace ImPlot {
|
||||
|
||||
// Creates a new ImPlot context. Call this after ImGui::CreateContext.
|
||||
IMPLOT_API ImPlotContext* CreateContext();
|
||||
// Destroys an ImPlot context. Call this before ImGui::DestroyContext. NULL = destroy current context.
|
||||
IMPLOT_API void DestroyContext(ImPlotContext* ctx = NULL);
|
||||
// Returns the current ImPlot context. NULL if no context has ben set.
|
||||
// Destroys an ImPlot context. Call this before ImGui::DestroyContext. nullptr = destroy current context.
|
||||
IMPLOT_API void DestroyContext(ImPlotContext* ctx = nullptr);
|
||||
// Returns the current ImPlot context. nullptr if no context has ben set.
|
||||
IMPLOT_API ImPlotContext* GetCurrentContext();
|
||||
// Sets the current ImPlot context.
|
||||
IMPLOT_API void SetCurrentContext(ImPlotContext* ctx);
|
||||
@@ -690,8 +690,8 @@ IMPLOT_API bool BeginSubplots(const char* title_id,
|
||||
int cols,
|
||||
const ImVec2& size,
|
||||
ImPlotSubplotFlags flags = 0,
|
||||
float* row_ratios = NULL,
|
||||
float* col_ratios = NULL);
|
||||
float* row_ratios = nullptr,
|
||||
float* col_ratios = nullptr);
|
||||
|
||||
// Only call EndSubplots() if BeginSubplots() returns true! Typically called at the end
|
||||
// of an if statement conditioned on BeginSublots(). See example above.
|
||||
@@ -726,24 +726,24 @@ IMPLOT_API void EndSubplots();
|
||||
// call it yourself, then the first subsequent plotting or utility function will
|
||||
// call it for you.
|
||||
|
||||
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = NULL for no label.
|
||||
IMPLOT_API void SetupAxis(ImAxis axis, const char* label=NULL, ImPlotAxisFlags flags=0);
|
||||
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
|
||||
// Enables an axis or sets the label and/or flags for an existing axis. Leave #label = nullptr for no label.
|
||||
IMPLOT_API void SetupAxis(ImAxis axis, const char* label=nullptr, ImPlotAxisFlags flags=0);
|
||||
// Sets an axis range limits. If ImPlotCond_Always is used, the axes limits will be locked. Inversion with v_min > v_max is not supported; use SetupAxisLimits instead.
|
||||
IMPLOT_API void SetupAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
|
||||
// Links an axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot.
|
||||
// Links an axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot.
|
||||
IMPLOT_API void SetupAxisLinks(ImAxis axis, double* link_min, double* link_max);
|
||||
// Sets the format of numeric axis labels via formater specifier (default="%g"). Formated values will be double (i.e. use %f).
|
||||
IMPLOT_API void SetupAxisFormat(ImAxis axis, const char* fmt);
|
||||
// Sets the format of numeric axis labels via formatter callback. Given #value, write a label into #buff. Optionally pass user data.
|
||||
IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=NULL);
|
||||
IMPLOT_API void SetupAxisFormat(ImAxis axis, ImPlotFormatter formatter, void* data=nullptr);
|
||||
// Sets an axis' ticks and optionally the labels. To keep the default ticks, set #keep_default=true.
|
||||
IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=NULL, bool keep_default=false);
|
||||
IMPLOT_API void SetupAxisTicks(ImAxis axis, const double* values, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);
|
||||
// Sets an axis' ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.
|
||||
IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=NULL, bool keep_default=false);
|
||||
IMPLOT_API void SetupAxisTicks(ImAxis axis, double v_min, double v_max, int n_ticks, const char* const labels[]=nullptr, bool keep_default=false);
|
||||
// Sets an axis' scale using built-in options.
|
||||
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotScale scale);
|
||||
// Sets an axis' scale using user supplied forward and inverse transfroms.
|
||||
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=NULL);
|
||||
IMPLOT_API void SetupAxisScale(ImAxis axis, ImPlotTransform forward, ImPlotTransform inverse, void* data=nullptr);
|
||||
// Sets an axis' limits constraints.
|
||||
IMPLOT_API void SetupAxisLimitsConstraints(ImAxis axis, double v_min, double v_max);
|
||||
// Sets an axis' zoom constraints.
|
||||
@@ -788,7 +788,7 @@ IMPLOT_API void SetupFinish();
|
||||
|
||||
// Sets an upcoming axis range limits. If ImPlotCond_Always is used, the axes limits will be locked.
|
||||
IMPLOT_API void SetNextAxisLimits(ImAxis axis, double v_min, double v_max, ImPlotCond cond = ImPlotCond_Once);
|
||||
// Links an upcoming axis range limits to external values. Set to NULL for no linkage. The pointer data must remain valid until EndPlot!
|
||||
// Links an upcoming axis range limits to external values. Set to nullptr for no linkage. The pointer data must remain valid until EndPlot!
|
||||
IMPLOT_API void SetNextAxisLinks(ImAxis axis, double* link_min, double* link_max);
|
||||
// Set an upcoming axis to auto fit to its data.
|
||||
IMPLOT_API void SetNextAxisToFit(ImAxis axis);
|
||||
@@ -890,10 +890,10 @@ IMPLOT_TMP void PlotStems(const char* label_id, const T* xs, const T* ys, int co
|
||||
// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).
|
||||
IMPLOT_TMP void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags=0, int offset=0, int stride=sizeof(T));
|
||||
|
||||
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to NULL for no labels.
|
||||
// Plots a pie chart. Center and radius are in plot units. #label_fmt can be set to nullptr for no labels.
|
||||
IMPLOT_TMP void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* label_fmt="%.1f", double angle0=90, ImPlotPieChartFlags flags=0);
|
||||
|
||||
// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to NULL for no labels.
|
||||
// Plots a 2D heatmap chart. Values are expected to be in row-major order by default. Leave #scale_min and scale_max both at 0 for automatic color scaling, or set them to a predefined range. #label_fmt can be set to nullptr for no labels.
|
||||
IMPLOT_TMP void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min=0, double scale_max=0, const char* label_fmt="%.1f", const ImPlotPoint& bounds_min=ImPlotPoint(0,0), const ImPlotPoint& bounds_max=ImPlotPoint(1,1), ImPlotHeatmapFlags flags=0);
|
||||
|
||||
// Plots a horizontal histogram. #bins can be a positive integer or an ImPlotBin_ method. If #range is left unspecified, the min/max of #values will be used as the range.
|
||||
@@ -1077,13 +1077,13 @@ IMPLOT_API void EndDragDropSource();
|
||||
IMPLOT_API ImPlotStyle& GetStyle();
|
||||
|
||||
// Style plot colors for current ImGui style (default).
|
||||
IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = NULL);
|
||||
IMPLOT_API void StyleColorsAuto(ImPlotStyle* dst = nullptr);
|
||||
// Style plot colors for ImGui "Classic".
|
||||
IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = NULL);
|
||||
IMPLOT_API void StyleColorsClassic(ImPlotStyle* dst = nullptr);
|
||||
// Style plot colors for ImGui "Dark".
|
||||
IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = NULL);
|
||||
IMPLOT_API void StyleColorsDark(ImPlotStyle* dst = nullptr);
|
||||
// Style plot colors for ImGui "Light".
|
||||
IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = NULL);
|
||||
IMPLOT_API void StyleColorsLight(ImPlotStyle* dst = nullptr);
|
||||
|
||||
// Use PushStyleX to temporarily modify your ImPlotStyle. The modification
|
||||
// will last until the matching call to PopStyleX. You MUST call a pop for
|
||||
@@ -1150,7 +1150,7 @@ IMPLOT_API ImPlotColormap AddColormap(const char* name, const ImU32* cols, int
|
||||
|
||||
// Returns the number of available colormaps (i.e. the built-in + user-added count).
|
||||
IMPLOT_API int GetColormapCount();
|
||||
// Returns a null terminated string name for a colormap given an index. Returns NULL if index is invalid.
|
||||
// Returns a null terminated string name for a colormap given an index. Returns nullptr if index is invalid.
|
||||
IMPLOT_API const char* GetColormapName(ImPlotColormap cmap);
|
||||
// Returns an index number for a colormap given a valid string name. Returns -1 if name is invalid.
|
||||
IMPLOT_API ImPlotColormap GetColormapIndex(const char* name);
|
||||
@@ -1179,18 +1179,18 @@ IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel"). If scale_min > scale_max, the scale to color mapping will be reversed.
|
||||
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), const char* format = "%g", ImPlotColormapScaleFlags flags = 0, ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
|
||||
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = NULL, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = nullptr, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
// Shows a button with a colormap gradient brackground.
|
||||
IMPLOT_API bool ColormapButton(const char* label, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);
|
||||
|
||||
// When items in a plot sample their color from a colormap, the color is cached and does not change
|
||||
// unless explicitly overriden. Therefore, if you change the colormap after the item has already been plotted,
|
||||
// item colors will NOT update. If you need item colors to resample the new colormap, then use this
|
||||
// function to bust the cached colors. If #plot_title_id is NULL, then every item in EVERY existing plot
|
||||
// function to bust the cached colors. If #plot_title_id is nullptr, then every item in EVERY existing plot
|
||||
// will be cache busted. Otherwise only the plot specified by #plot_title_id will be busted. For the
|
||||
// latter, this function must be called in the same ImGui ID scope that the plot is in. You should rarely if ever
|
||||
// need this function, but it is available for applications that require runtime colormap swaps (e.g. Heatmaps demo).
|
||||
IMPLOT_API void BustColorCache(const char* plot_title_id = NULL);
|
||||
IMPLOT_API void BustColorCache(const char* plot_title_id = nullptr);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Input Mapping
|
||||
@@ -1200,9 +1200,9 @@ IMPLOT_API void BustColorCache(const char* plot_title_id = NULL);
|
||||
IMPLOT_API ImPlotInputMap& GetInputMap();
|
||||
|
||||
// Default input mapping: pan = LMB drag, box select = RMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
|
||||
IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = NULL);
|
||||
IMPLOT_API void MapInputDefault(ImPlotInputMap* dst = nullptr);
|
||||
// Reverse input mapping: pan = RMB drag, box select = LMB drag, fit = LMB double click, context menu = RMB click, zoom = scroll.
|
||||
IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = NULL);
|
||||
IMPLOT_API void MapInputReverse(ImPlotInputMap* dst = nullptr);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Miscellaneous
|
||||
@@ -1227,18 +1227,18 @@ IMPLOT_API bool ShowColormapSelector(const char* label);
|
||||
// Shows ImPlot input map selector dropdown menu.
|
||||
IMPLOT_API bool ShowInputMapSelector(const char* label);
|
||||
// Shows ImPlot style editor block (not a window).
|
||||
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = NULL);
|
||||
IMPLOT_API void ShowStyleEditor(ImPlotStyle* ref = nullptr);
|
||||
// Add basic help/info block for end users (not a window).
|
||||
IMPLOT_API void ShowUserGuide();
|
||||
// Shows ImPlot metrics/debug information window.
|
||||
IMPLOT_API void ShowMetricsWindow(bool* p_popen = NULL);
|
||||
IMPLOT_API void ShowMetricsWindow(bool* p_popen = nullptr);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Demo
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Shows the ImPlot demo window (add implot_demo.cpp to your sources!)
|
||||
IMPLOT_API void ShowDemoWindow(bool* p_open = NULL);
|
||||
IMPLOT_API void ShowDemoWindow(bool* p_open = nullptr);
|
||||
|
||||
} // namespace ImPlot
|
||||
|
||||
@@ -1276,16 +1276,16 @@ namespace ImPlot {
|
||||
|
||||
// OBSOLETED in v0.13 -> PLANNED REMOVAL in v1.0
|
||||
IMPLOT_DEPRECATED( IMPLOT_API bool BeginPlot(const char* title_id,
|
||||
const char* x_label, // = NULL,
|
||||
const char* y_label, // = NULL,
|
||||
const char* x_label, // = nullptr,
|
||||
const char* y_label, // = nullptr,
|
||||
const ImVec2& size = ImVec2(-1,0),
|
||||
ImPlotFlags flags = ImPlotFlags_None,
|
||||
ImPlotAxisFlags x_flags = 0,
|
||||
ImPlotAxisFlags y_flags = 0,
|
||||
ImPlotAxisFlags y2_flags = ImPlotAxisFlags_AuxDefault,
|
||||
ImPlotAxisFlags y3_flags = ImPlotAxisFlags_AuxDefault,
|
||||
const char* y2_label = NULL,
|
||||
const char* y3_label = NULL) );
|
||||
const char* y2_label = nullptr,
|
||||
const char* y3_label = nullptr) );
|
||||
|
||||
} // namespace ImPlot
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2022 Evan Pezent
|
||||
// Copyright (c) 2023 Evan Pezent
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -20,7 +20,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// ImPlot v0.14
|
||||
// ImPlot v0.16
|
||||
|
||||
// You may use this file to debug, understand or extend ImPlot features but we
|
||||
// don't provide any guarantee of forward compatibility!
|
||||
@@ -31,10 +31,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include "imgui/imgui_internal.h"
|
||||
|
||||
@@ -400,18 +396,18 @@ struct ImPlotColormapData {
|
||||
_AppendTable(i);
|
||||
}
|
||||
|
||||
inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
|
||||
inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : NULL; }
|
||||
inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
|
||||
inline bool IsQual(ImPlotColormap cmap) const { return Quals[cmap]; }
|
||||
inline const char* GetName(ImPlotColormap cmap) const { return cmap < Count ? Text.Buf.Data + TextOffsets[cmap] : nullptr; }
|
||||
inline ImPlotColormap GetIndex(const char* name) const { ImGuiID key = ImHashStr(name); return Map.GetInt(key,-1); }
|
||||
|
||||
inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
|
||||
inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; }
|
||||
inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; }
|
||||
inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
|
||||
inline const ImU32* GetKeys(ImPlotColormap cmap) const { return &Keys[KeyOffsets[cmap]]; }
|
||||
inline int GetKeyCount(ImPlotColormap cmap) const { return KeyCounts[cmap]; }
|
||||
inline ImU32 GetKeyColor(ImPlotColormap cmap, int idx) const { return Keys[KeyOffsets[cmap]+idx]; }
|
||||
inline void SetKeyColor(ImPlotColormap cmap, int idx, ImU32 value) { Keys[KeyOffsets[cmap]+idx] = value; RebuildTables(); }
|
||||
|
||||
inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; }
|
||||
inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; }
|
||||
inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; }
|
||||
inline const ImU32* GetTable(ImPlotColormap cmap) const { return &Tables[TableOffsets[cmap]]; }
|
||||
inline int GetTableSize(ImPlotColormap cmap) const { return TableSizes[cmap]; }
|
||||
inline ImU32 GetTableColor(ImPlotColormap cmap, int idx) const { return Tables[TableOffsets[cmap]+idx]; }
|
||||
|
||||
inline ImU32 LerpTable(ImPlotColormap cmap, float t) const {
|
||||
int off = TableOffsets[cmap];
|
||||
@@ -568,7 +564,7 @@ struct ImPlotTicker {
|
||||
|
||||
ImPlotTick& AddTick(double value, bool major, int level, bool show_label, const char* label) {
|
||||
ImPlotTick tick(value, major, level, show_label);
|
||||
if (show_label && label != NULL) {
|
||||
if (show_label && label != nullptr) {
|
||||
tick.TextOffset = TextBuffer.size();
|
||||
TextBuffer.append(label, label + strlen(label) + 1);
|
||||
tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
|
||||
@@ -578,7 +574,7 @@ struct ImPlotTicker {
|
||||
|
||||
ImPlotTick& AddTick(double value, bool major, int level, bool show_label, ImPlotFormatter formatter, void* data) {
|
||||
ImPlotTick tick(value, major, level, show_label);
|
||||
if (show_label && formatter != NULL) {
|
||||
if (show_label && formatter != nullptr) {
|
||||
char buff[IMPLOT_LABEL_MAX_SIZE];
|
||||
tick.TextOffset = TextBuffer.size();
|
||||
formatter(tick.PlotPos, buff, sizeof(buff), data);
|
||||
@@ -677,23 +673,23 @@ struct ImPlotAxis
|
||||
Range.Min = 0;
|
||||
Range.Max = 1;
|
||||
Scale = ImPlotScale_Linear;
|
||||
TransformForward = TransformInverse = NULL;
|
||||
TransformData = NULL;
|
||||
TransformForward = TransformInverse = nullptr;
|
||||
TransformData = nullptr;
|
||||
FitExtents.Min = HUGE_VAL;
|
||||
FitExtents.Max = -HUGE_VAL;
|
||||
OrthoAxis = NULL;
|
||||
OrthoAxis = nullptr;
|
||||
ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
|
||||
ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
|
||||
LinkedMin = LinkedMax = NULL;
|
||||
LinkedMin = LinkedMax = nullptr;
|
||||
PickerLevel = 0;
|
||||
Datum1 = Datum2 = 0;
|
||||
PixelMin = PixelMax = 0;
|
||||
LabelOffset = -1;
|
||||
ColorMaj = ColorMin = ColorTick = ColorTxt = ColorBg = ColorHov = ColorAct = 0;
|
||||
ColorHiLi = IM_COL32_BLACK_TRANS;
|
||||
Formatter = NULL;
|
||||
FormatterData = NULL;
|
||||
Locator = NULL;
|
||||
Formatter = nullptr;
|
||||
FormatterData = nullptr;
|
||||
Locator = nullptr;
|
||||
Enabled = Hovered = Held = FitThisFrame = HasRange = HasFormatSpec = false;
|
||||
ShowDefaultTicks = true;
|
||||
}
|
||||
@@ -701,18 +697,18 @@ struct ImPlotAxis
|
||||
inline void Reset() {
|
||||
Enabled = false;
|
||||
Scale = ImPlotScale_Linear;
|
||||
TransformForward = TransformInverse = NULL;
|
||||
TransformData = NULL;
|
||||
TransformForward = TransformInverse = nullptr;
|
||||
TransformData = nullptr;
|
||||
LabelOffset = -1;
|
||||
HasFormatSpec = false;
|
||||
Formatter = NULL;
|
||||
FormatterData = NULL;
|
||||
Locator = NULL;
|
||||
Formatter = nullptr;
|
||||
FormatterData = nullptr;
|
||||
Locator = nullptr;
|
||||
ShowDefaultTicks = true;
|
||||
FitThisFrame = false;
|
||||
FitExtents.Min = HUGE_VAL;
|
||||
FitExtents.Max = -HUGE_VAL;
|
||||
OrthoAxis = NULL;
|
||||
OrthoAxis = nullptr;
|
||||
ConstraintRange = ImPlotRange(-INFINITY,INFINITY);
|
||||
ConstraintZoom = ImPlotRange(DBL_MIN,INFINITY);
|
||||
Ticker.Reset();
|
||||
@@ -810,7 +806,7 @@ struct ImPlotAxis
|
||||
|
||||
inline void UpdateTransformCache() {
|
||||
ScaleToPixel = (PixelMax - PixelMin) / Range.Size();
|
||||
if (TransformForward != NULL) {
|
||||
if (TransformForward != nullptr) {
|
||||
ScaleMin = TransformForward(Range.Min, TransformData);
|
||||
ScaleMax = TransformForward(Range.Max, TransformData);
|
||||
}
|
||||
@@ -821,7 +817,7 @@ struct ImPlotAxis
|
||||
}
|
||||
|
||||
inline float PlotToPixels(double plt) const {
|
||||
if (TransformForward != NULL) {
|
||||
if (TransformForward != nullptr) {
|
||||
double s = TransformForward(plt, TransformData);
|
||||
double t = (s - ScaleMin) / (ScaleMax - ScaleMin);
|
||||
plt = Range.Min + Range.Size() * t;
|
||||
@@ -832,7 +828,7 @@ struct ImPlotAxis
|
||||
|
||||
inline double PixelsToPlot(float pix) const {
|
||||
double plt = (pix - PixelMin) / ScaleToPixel + Range.Min;
|
||||
if (TransformInverse != NULL) {
|
||||
if (TransformInverse != nullptr) {
|
||||
double t = (plt - Range.Min) / Range.Size();
|
||||
double s = t * (ScaleMax - ScaleMin) + ScaleMin;
|
||||
plt = TransformInverse(s, TransformData);
|
||||
@@ -911,8 +907,9 @@ struct ImPlotAxis
|
||||
}
|
||||
|
||||
void PullLinks() {
|
||||
if (LinkedMin) { SetMin(*LinkedMin,true); }
|
||||
if (LinkedMax) { SetMax(*LinkedMax,true); }
|
||||
if (LinkedMin && LinkedMax) { SetRange(*LinkedMin, *LinkedMax); }
|
||||
else if (LinkedMin) { SetMin(*LinkedMin,true); }
|
||||
else if (LinkedMax) { SetMax(*LinkedMax,true); }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1071,7 +1068,7 @@ struct ImPlotPlot
|
||||
inline void ClearTextBuffer() { TextBuffer.Buf.shrink(0); }
|
||||
|
||||
inline void SetTitle(const char* title) {
|
||||
if (title && ImGui::FindRenderedTextEnd(title, NULL) != title) {
|
||||
if (title && ImGui::FindRenderedTextEnd(title, nullptr) != title) {
|
||||
TitleOffset = TextBuffer.size();
|
||||
TextBuffer.append(title, title + strlen(title) + 1);
|
||||
}
|
||||
@@ -1102,7 +1099,7 @@ struct ImPlotPlot
|
||||
}
|
||||
|
||||
inline void SetAxisLabel(ImPlotAxis& axis, const char* label) {
|
||||
if (label && ImGui::FindRenderedTextEnd(label, NULL) != label) {
|
||||
if (label && ImGui::FindRenderedTextEnd(label, nullptr) != label) {
|
||||
axis.LabelOffset = TextBuffer.size();
|
||||
TextBuffer.append(label, label + strlen(label) + 1);
|
||||
}
|
||||
@@ -1140,7 +1137,6 @@ struct ImPlotSubplot {
|
||||
ID = 0;
|
||||
Flags = PreviousFlags = ImPlotSubplotFlags_None;
|
||||
Rows = Cols = CurrentIdx = 0;
|
||||
FrameHovered = false;
|
||||
Items.Legend.Location = ImPlotLocation_North;
|
||||
Items.Legend.Flags = ImPlotLegendFlags_Horizontal|ImPlotLegendFlags_Outside;
|
||||
Items.Legend.CanGoInside = false;
|
||||
@@ -1166,7 +1162,7 @@ struct ImPlotNextPlotData
|
||||
for (int i = 0; i < ImAxis_COUNT; ++i) {
|
||||
HasRange[i] = false;
|
||||
Fit[i] = false;
|
||||
LinkedMin[i] = LinkedMax[i] = NULL;
|
||||
LinkedMin[i] = LinkedMax[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1292,9 +1288,10 @@ IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
|
||||
|
||||
// Lock Setup and call SetupFinish if necessary.
|
||||
static inline void SetupLock() {
|
||||
if (!GImPlot->CurrentPlot->SetupLocked)
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (!gp.CurrentPlot->SetupLocked)
|
||||
SetupFinish();
|
||||
GImPlot->CurrentPlot->SetupLocked = true;
|
||||
gp.CurrentPlot->SetupLocked = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1330,7 +1327,7 @@ bool BeginItemEx(const char* label_id, const _Fitter& fitter, ImPlotItemFlags fl
|
||||
IMPLOT_API void EndItem();
|
||||
|
||||
// Register or get an existing item from the current plot.
|
||||
IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = NULL);
|
||||
IMPLOT_API ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created = nullptr);
|
||||
// Get a plot item from the current plot.
|
||||
IMPLOT_API ImPlotItem* GetItem(const char* label_id);
|
||||
// Gets the current item.
|
||||
@@ -1442,7 +1439,7 @@ static inline const ImPlotNextItemData& GetItemData() { return GImPlot->NextItem
|
||||
|
||||
// Returns true if a color is set to be automatically determined
|
||||
static inline bool IsColorAuto(const ImVec4& col) { return col.w == -1; }
|
||||
// Returns true if a style color is set to be automaticaly determined
|
||||
// Returns true if a style color is set to be automatically determined
|
||||
static inline bool IsColorAuto(ImPlotCol idx) { return IsColorAuto(GImPlot->Style.Colors[idx]); }
|
||||
// Returns the automatically deduced style color
|
||||
IMPLOT_API ImVec4 GetAutoColor(ImPlotCol idx);
|
||||
@@ -1452,9 +1449,9 @@ static inline ImVec4 GetStyleColorVec4(ImPlotCol idx) { return IsColorAuto(idx)
|
||||
static inline ImU32 GetStyleColorU32(ImPlotCol idx) { return ImGui::ColorConvertFloat4ToU32(GetStyleColorVec4(idx)); }
|
||||
|
||||
// Draws vertical text. The position is the bottom left of the text rect.
|
||||
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
|
||||
IMPLOT_API void AddTextVertical(ImDrawList *DrawList, ImVec2 pos, ImU32 col, const char* text_begin, const char* text_end = nullptr);
|
||||
// Draws multiline horizontal text centered.
|
||||
IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = NULL);
|
||||
IMPLOT_API void AddTextCentered(ImDrawList* DrawList, ImVec2 top_center, ImU32 col, const char* text_begin, const char* text_end = nullptr);
|
||||
// Calculates the size of vertical text
|
||||
static inline ImVec2 CalcTextSizeVertical(const char *text) {
|
||||
ImVec2 sz = ImGui::CalcTextSize(text);
|
||||
@@ -1593,7 +1590,7 @@ IMPLOT_API int FormatDateTime(const ImPlotTime& t, char* buffer, int size, ImPlo
|
||||
// #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
|
||||
// #t will be set when a day is clicked and the function will return true.
|
||||
// #t1 and #t2 are optional dates to highlight.
|
||||
IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = NULL, const ImPlotTime* t2 = NULL);
|
||||
IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = nullptr, const ImPlotTime* t2 = nullptr);
|
||||
// Shows a time picker widget block (hour/min/sec).
|
||||
// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
|
||||
IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2020 Evan Pezent
|
||||
// Copyright (c) 2023 Evan Pezent
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -20,8 +20,9 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// ImPlot v0.14
|
||||
// ImPlot v0.16
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include "implot.h"
|
||||
#include "implot_internal.h"
|
||||
|
||||
@@ -81,7 +82,7 @@ static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); }
|
||||
// unsigned long long ImU64; // 64-bit unsigned integer
|
||||
// (note: this list does *not* include `long`, `unsigned long` and `long double`)
|
||||
//
|
||||
// You can customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list.
|
||||
// You can customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list.
|
||||
// As an example, you could use the compile time define given by the line below in order to support only float and double.
|
||||
// -DIMPLOT_CUSTOM_NUMERIC_TYPES="(float)(double)"
|
||||
// In order to support all known C++ types, use:
|
||||
@@ -97,11 +98,11 @@ static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); }
|
||||
#define _CAT(x, y) _CAT_(x, y)
|
||||
#define _CAT_(x,y) x ## y
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END)
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_2
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T); _INSTANTIATE_FOR_NUMERIC_TYPES_1
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_2
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_1
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES_1_END
|
||||
#define _INSTANTIATE_FOR_NUMERIC_TYPES_2_END
|
||||
#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES);
|
||||
#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES)
|
||||
|
||||
namespace ImPlot {
|
||||
|
||||
@@ -284,15 +285,15 @@ ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool*
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
ImPlotItemGroup& Items = *gp.CurrentItems;
|
||||
ImGuiID id = Items.GetItemID(label_id);
|
||||
if (just_created != NULL)
|
||||
*just_created = Items.GetItem(id) == NULL;
|
||||
if (just_created != nullptr)
|
||||
*just_created = Items.GetItem(id) == nullptr;
|
||||
ImPlotItem* item = Items.GetOrAddItem(id);
|
||||
if (item->SeenThisFrame)
|
||||
return item;
|
||||
item->SeenThisFrame = true;
|
||||
int idx = Items.GetItemIndex(item);
|
||||
item->ID = id;
|
||||
if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, NULL) != label_id) {
|
||||
if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, nullptr) != label_id) {
|
||||
Items.Legend.Indices.push_back(idx);
|
||||
item->NameOffset = Items.Legend.Labels.size();
|
||||
Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1);
|
||||
@@ -310,7 +311,7 @@ ImPlotItem* GetItem(const char* label_id) {
|
||||
|
||||
bool IsItemHidden(const char* label_id) {
|
||||
ImPlotItem* item = GetItem(label_id);
|
||||
return item != NULL && !item->Show;
|
||||
return item != nullptr && !item->Show;
|
||||
}
|
||||
|
||||
ImPlotItem* GetCurrentItem() {
|
||||
@@ -367,17 +368,17 @@ void BustItemCache() {
|
||||
|
||||
void BustColorCache(const char* plot_title_id) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
if (plot_title_id == NULL) {
|
||||
if (plot_title_id == nullptr) {
|
||||
BustItemCache();
|
||||
}
|
||||
else {
|
||||
ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id);
|
||||
ImPlotPlot* plot = gp.Plots.GetByKey(id);
|
||||
if (plot != NULL)
|
||||
if (plot != nullptr)
|
||||
plot->Items.Reset();
|
||||
else {
|
||||
ImPlotSubplot* subplot = gp.Subplots.GetByKey(id);
|
||||
if (subplot != NULL)
|
||||
if (subplot != nullptr)
|
||||
subplot->Items.Reset();
|
||||
}
|
||||
}
|
||||
@@ -393,7 +394,7 @@ static const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f;
|
||||
// Begins a new item. Returns false if the item should not be plotted.
|
||||
bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "PlotX() needs to be called between BeginPlot() and EndPlot()!");
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotX() needs to be called between BeginPlot() and EndPlot()!");
|
||||
SetupLock();
|
||||
bool just_created;
|
||||
ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created);
|
||||
@@ -421,7 +422,7 @@ bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_fr
|
||||
// reset next item data
|
||||
gp.NextItemData.Reset();
|
||||
gp.PreviousItem = item;
|
||||
gp.CurrentItem = NULL;
|
||||
gp.CurrentItem = nullptr;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
@@ -480,7 +481,7 @@ void EndItem() {
|
||||
gp.NextItemData.Reset();
|
||||
// set current item
|
||||
gp.PreviousItem = gp.CurrentItem;
|
||||
gp.CurrentItem = NULL;
|
||||
gp.CurrentItem = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -784,7 +785,7 @@ struct Transformer1 {
|
||||
{ }
|
||||
|
||||
template <typename T> IMPLOT_INLINE float operator()(T p) const {
|
||||
if (TransformFwd != NULL) {
|
||||
if (TransformFwd != nullptr) {
|
||||
double s = TransformFwd(p, TransformData);
|
||||
double t = (s - ScaMin) / (ScaMax - ScaMin);
|
||||
p = PltMin + (PltMax - PltMin) * t;
|
||||
@@ -1899,8 +1900,9 @@ void PlotBarGroups(const char* const label_ids[], const T* values, int item_coun
|
||||
const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked);
|
||||
if (stack) {
|
||||
SetupLock();
|
||||
GImPlot->TempDouble1.resize(4*group_count);
|
||||
double* temp = GImPlot->TempDouble1.Data;
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
gp.TempDouble1.resize(4*group_count);
|
||||
double* temp = gp.TempDouble1.Data;
|
||||
double* neg = &temp[0];
|
||||
double* pos = &temp[group_count];
|
||||
double* curr_min = &temp[group_count*2];
|
||||
@@ -2171,7 +2173,7 @@ IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& cent
|
||||
|
||||
template <typename T>
|
||||
void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) {
|
||||
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
|
||||
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!");
|
||||
ImDrawList & draw_list = *GetPlotDrawList();
|
||||
double sum = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
@@ -2199,7 +2201,7 @@ void PlotPieChart(const char* const label_ids[], const T* values, int count, dou
|
||||
}
|
||||
a0 = a1;
|
||||
}
|
||||
if (fmt != NULL) {
|
||||
if (fmt != nullptr) {
|
||||
a0 = angle0 * 2 * IM_PI / 360.0;
|
||||
a1 = angle0 * 2 * IM_PI / 360.0;
|
||||
char buffer[32];
|
||||
@@ -2253,7 +2255,8 @@ struct GetterHeatmapRowMaj {
|
||||
rect.Pos = p;
|
||||
rect.HalfSize = HalfSize;
|
||||
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
|
||||
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t);
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);
|
||||
return rect;
|
||||
}
|
||||
const T* const Values;
|
||||
@@ -2287,7 +2290,8 @@ struct GetterHeatmapColMaj {
|
||||
rect.Pos = p;
|
||||
rect.HalfSize = HalfSize;
|
||||
const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f);
|
||||
rect.Color = GImPlot->ColormapData.LerpTable(GImPlot->Style.Colormap, t);
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t);
|
||||
return rect;
|
||||
}
|
||||
const T* const Values;
|
||||
@@ -2324,7 +2328,7 @@ void RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, d
|
||||
RenderPrimitives1<RendererRectC>(getter);
|
||||
}
|
||||
// labels
|
||||
if (fmt != NULL) {
|
||||
if (fmt != nullptr) {
|
||||
const double w = (bounds_max.x - bounds_min.x) / cols;
|
||||
const double h = (bounds_max.y - bounds_min.y) / rows;
|
||||
const ImPlotPoint half_size(w*0.5,h*0.5);
|
||||
@@ -2408,8 +2412,9 @@ double PlotHistogram(const char* label_id, const T* values, int count, int bins,
|
||||
else
|
||||
width = range.Size() / bins;
|
||||
|
||||
ImVector<double>& bin_centers = GImPlot->TempDouble1;
|
||||
ImVector<double>& bin_counts = GImPlot->TempDouble2;
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
ImVector<double>& bin_centers = gp.TempDouble1;
|
||||
ImVector<double>& bin_counts = gp.TempDouble2;
|
||||
bin_centers.resize(bins);
|
||||
bin_counts.resize(bins);
|
||||
int below = 0;
|
||||
@@ -2506,7 +2511,8 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
|
||||
|
||||
const int bins = x_bins * y_bins;
|
||||
|
||||
ImVector<double>& bin_counts = GImPlot->TempDouble1;
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
ImVector<double>& bin_counts = gp.TempDouble1;
|
||||
bin_counts.resize(bins);
|
||||
|
||||
for (int b = 0; b < bins; ++b)
|
||||
@@ -2534,7 +2540,7 @@ double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count
|
||||
|
||||
if (BeginItemEx(label_id, FitterRect(range))) {
|
||||
ImDrawList& draw_list = *GetPlotDrawList();
|
||||
RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, NULL, range.Min(), range.Max(), false, col_maj);
|
||||
RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj);
|
||||
EndItem();
|
||||
}
|
||||
return max_count;
|
||||
@@ -2591,8 +2597,8 @@ void PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags
|
||||
//do not extend plot outside plot range
|
||||
if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin;
|
||||
if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin;
|
||||
if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax;
|
||||
if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax;
|
||||
if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976
|
||||
if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976
|
||||
//plot a rectangle that extends up to x2 with y1 height
|
||||
if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) {
|
||||
// ImVec4 colAlpha = item->Color;
|
||||
@@ -2647,7 +2653,7 @@ void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPo
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) {
|
||||
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != NULL, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
|
||||
IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotText() needs to be called between BeginPlot() and EndPlot()!");
|
||||
SetupLock();
|
||||
ImDrawList & draw_list = *GetPlotDrawList();
|
||||
PushPlotClipRect();
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -115,7 +115,11 @@ static GL3WglProc (*glx_get_proc_address)(const GLubyte *);
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
#if defined(__OpenBSD__)
|
||||
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
|
||||
#else
|
||||
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
#endif
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
Submodule core/deps/libchdr updated: 2781322c4a...925400c4c4.
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.7.2)
|
||||
|
||||
project(libelf C)
|
||||
|
||||
add_library(elf STATIC EXCLUDE_FROM_ALL src/elf.c src/elf32.c src/elf64.c)
|
||||
target_include_directories(elf PUBLIC include)
|
||||
target_link_libraries(elf)
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
#ifndef __ELF_DEBUG_32_H__
|
||||
#define __ELF_DEBUG_32_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "elf32.h"
|
||||
|
||||
void elf32_fprintf(FILE *f, struct Elf32_Header *file, int size, const char *name, int flags);
|
||||
|
||||
#endif /* __ELF_DEBUG_32_H__ */
|
||||
@@ -1,376 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "elf.h"
|
||||
#include "debug.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef UINT64_MAX
|
||||
# define UINT64_MAX (__UINT64_C(18446744073709551615))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Checks that elfFile points to a valid elf file. Returns 0 if the elf
|
||||
* file is valid, < 0 if invalid.
|
||||
*/
|
||||
|
||||
#define ISELF32(elfFile) ( ((struct Elf32_Header*)elfFile)->e_ident[EI_CLASS] == ELFCLASS32 )
|
||||
#define ISELF64(elfFile) ( ((struct Elf64_Header*)elfFile)->e_ident[EI_CLASS] == ELFCLASS64 )
|
||||
|
||||
int
|
||||
elf_checkFile(void *elfFile)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_checkFile((Elf32_Header*)elfFile)
|
||||
: elf64_checkFile((Elf64_Header*)elfFile);
|
||||
}
|
||||
|
||||
/* Program Headers Access functions */
|
||||
uint16_t
|
||||
elf_getNumProgramHeaders(void *elfFile)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getNumProgramHeaders((Elf32_Header*)elfFile)
|
||||
: elf64_getNumProgramHeaders((Elf64_Header*)elfFile);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf_getProgramHeaderFlags(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderFlags((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderFlags((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf_getProgramHeaderType(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderType((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderType((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getProgramHeaderPaddr(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderPaddr((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderPaddr((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getProgramHeaderVaddr(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderVaddr((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderVaddr((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getProgramHeaderMemorySize(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderMemorySize((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderMemorySize((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getProgramHeaderFileSize(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderFileSize((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderFileSize((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getProgramHeaderOffset(void *elfFile, uint16_t ph)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getProgramHeaderOffset((Elf32_Header*)elfFile, ph)
|
||||
: elf64_getProgramHeaderOffset((Elf64_Header*)elfFile, ph);
|
||||
}
|
||||
|
||||
char *
|
||||
elf_getSegmentStringTable(void *elfFile)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSegmentStringTable((Elf32_Header*)elfFile)
|
||||
: elf64_getSegmentStringTable((Elf64_Header*)elfFile);
|
||||
}
|
||||
|
||||
char *
|
||||
elf_getStringTable(void *elfFile, int string_segment)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getStringTable((Elf32_Header*)elfFile)
|
||||
: elf64_getStringTable((Elf64_Header*)elfFile, string_segment);
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
elf_getNumSections(void *elfFile)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getNumSections((Elf32_Header*)elfFile)
|
||||
: elf64_getNumSections((Elf64_Header*)elfFile);
|
||||
}
|
||||
|
||||
char *
|
||||
elf_getSectionName(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionName((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSectionName((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf_getSectionFlags(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionFlags((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSectionFlags((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf_getSectionType(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionType((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSectionType((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getSectionSize(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionSize((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSectionSize((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getSectionLink(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionLink((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSectionLink((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getSectionAddr(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionAddr((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSectionAddr((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
elf_getSection(void *elfFile, int i)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSection((Elf32_Header*)elfFile, i)
|
||||
: elf64_getSection((Elf64_Header*)elfFile, i);
|
||||
}
|
||||
|
||||
void *
|
||||
elf_getSectionNamed(void *elfFile, char *_str)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getSectionNamed((Elf32_Header*)elfFile, _str)
|
||||
: elf64_getSectionNamed((Elf64_Header*)elfFile, _str);
|
||||
}
|
||||
|
||||
void
|
||||
elf_getProgramHeaderInfo(void *elfFile, uint16_t ph, uint64_t *p_vaddr,
|
||||
uint64_t *p_paddr, uint64_t *p_filesz, uint64_t *p_offset,
|
||||
uint64_t *p_memsz)
|
||||
{
|
||||
*p_vaddr = elf_getProgramHeaderVaddr(elfFile, ph);
|
||||
*p_paddr = elf_getProgramHeaderPaddr(elfFile, ph);
|
||||
*p_filesz = elf_getProgramHeaderFileSize(elfFile, ph);
|
||||
*p_offset = elf_getProgramHeaderOffset(elfFile, ph);
|
||||
*p_memsz = elf_getProgramHeaderMemorySize(elfFile, ph);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_getEntryPoint(void *elfFile)
|
||||
{
|
||||
return ISELF32 (elfFile)
|
||||
? elf32_getEntryPoint ((Elf32_Header*)elfFile)
|
||||
: elf64_getEntryPoint ((Elf64_Header*)elfFile);
|
||||
}
|
||||
|
||||
void
|
||||
elf_fprintf(FILE *f, void *file, int size, const char *name, int flags)
|
||||
{
|
||||
elf32_fprintf(f, (Elf32_Header*)file, size, name, flags);
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
elf_getMemoryBounds(void *elfFile, bool phys, uint64_t *min, uint64_t *max)
|
||||
{
|
||||
uint64_t mem_min = UINT64_MAX;
|
||||
uint64_t mem_max = 0;
|
||||
int i;
|
||||
|
||||
if (elf_checkFile(elfFile) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i=0; i < elf_getNumProgramHeaders(elfFile); i++) {
|
||||
uint64_t sect_min, sect_max;
|
||||
|
||||
if (elf_getProgramHeaderMemorySize(elfFile, i) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (phys) {
|
||||
sect_min = elf_getProgramHeaderPaddr(elfFile, i);
|
||||
} else {
|
||||
sect_min = elf_getProgramHeaderVaddr(elfFile, i);
|
||||
}
|
||||
|
||||
sect_max = sect_min + elf_getProgramHeaderMemorySize(elfFile, i);
|
||||
|
||||
if (sect_max > mem_max) {
|
||||
mem_max = sect_max;
|
||||
}
|
||||
if (sect_min < mem_min) {
|
||||
mem_min = sect_min;
|
||||
}
|
||||
}
|
||||
*min = mem_min;
|
||||
*max = mem_max;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
elf_vaddrInProgramHeader(void *elfFile, uint16_t ph, uint64_t vaddr)
|
||||
{
|
||||
uint64_t min = elf_getProgramHeaderVaddr(elfFile, ph);
|
||||
uint64_t max = min + elf_getProgramHeaderMemorySize(elfFile, ph);
|
||||
if (vaddr >= min && vaddr < max) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf_vtopProgramHeader(void *elfFile, uint16_t ph, uint64_t vaddr)
|
||||
{
|
||||
uint64_t ph_phys = elf_getProgramHeaderPaddr(elfFile, ph);
|
||||
uint64_t ph_virt = elf_getProgramHeaderVaddr(elfFile, ph);
|
||||
uint64_t paddr;
|
||||
|
||||
paddr = vaddr - ph_virt + ph_phys;
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
bool
|
||||
elf_loadFile(void *elfFile, bool phys)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (elf_checkFile(elfFile) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i=0; i < elf_getNumProgramHeaders(elfFile); i++) {
|
||||
/* Load that section */
|
||||
uint64_t dest, src;
|
||||
size_t len;
|
||||
if (phys) {
|
||||
dest = elf_getProgramHeaderPaddr(elfFile, i);
|
||||
} else {
|
||||
dest = elf_getProgramHeaderVaddr(elfFile, i);
|
||||
}
|
||||
len = elf_getProgramHeaderFileSize(elfFile, i);
|
||||
src = (uint64_t) (uintptr_t) elfFile + elf_getProgramHeaderOffset(elfFile, i);
|
||||
memcpy((void*) (uintptr_t) dest, (void*) (uintptr_t) src, len);
|
||||
dest += len;
|
||||
memset((void*) (uintptr_t) dest, 0, elf_getProgramHeaderMemorySize(elfFile, i) - len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,392 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
|
||||
/*
|
||||
Authors: Luke Deller, Ben Leslie
|
||||
Created: 24/Sep/1999
|
||||
*/
|
||||
|
||||
/**
|
||||
\file
|
||||
|
||||
\brief Generic ELF library
|
||||
|
||||
The ELF library is designed to make the task of parsing and getting information
|
||||
out of an ELF file easier.
|
||||
|
||||
It provides function to obtain the various different fields in the ELF header, and
|
||||
the program and segment information.
|
||||
|
||||
Also importantly, it provides a function elf_loadFile which will load a given
|
||||
ELF file into memory.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ELF_ELF_H__
|
||||
#define __ELF_ELF_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "elf32.h"
|
||||
#include "elf64.h"
|
||||
|
||||
struct elf_symbol {
|
||||
uint32_t st_name; // Symbol name (string table index)
|
||||
uint32_t st_value; // Symbol value
|
||||
uint32_t st_size; // Symbol size
|
||||
uint8_t st_info; // Symbol type and binding
|
||||
uint8_t st_other; // No defined meaning, 0
|
||||
uint16_t st_shndx; // Section index
|
||||
};
|
||||
|
||||
struct elf64_symbol {
|
||||
uint32_t st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
uint16_t st_shndx;
|
||||
uint64_t st_value;
|
||||
uint64_t st_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* constants for Elf32_Phdr.p_flags
|
||||
*/
|
||||
#define PF_X 1 /* readable segment */
|
||||
#define PF_W 2 /* writeable segment */
|
||||
#define PF_R 4 /* executable segment */
|
||||
|
||||
/*
|
||||
* constants for indexing into Elf64_Header_t.e_ident
|
||||
*/
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
|
||||
#define ELFMAG0 '\177'
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
/* Section Header type bits */
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
|
||||
/* Section Header flag bits */
|
||||
#define SHF_WRITE 1
|
||||
#define SHF_ALLOC 2
|
||||
#define SHF_EXECINSTR 4
|
||||
|
||||
/**/
|
||||
#define ELF_PRINT_PROGRAM_HEADERS 1
|
||||
#define ELF_PRINT_SECTIONS 2
|
||||
#define ELF_PRINT_ALL (ELF_PRINT_PROGRAM_HEADERS | ELF_PRINT_SECTIONS)
|
||||
|
||||
/* Symbol types */
|
||||
#define STT_FUNC 2 /* Function, code */
|
||||
|
||||
/**
|
||||
* Checks that elfFile points to a valid elf file.
|
||||
*
|
||||
* @param elfFile Potential ELF file to check
|
||||
*
|
||||
* \return 0 on success. -1 if not and elf, -2 if not 32 bit.
|
||||
*/
|
||||
int elf_checkFile(void *elfFile);
|
||||
|
||||
/**
|
||||
* Determine number of sections in an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header.
|
||||
*
|
||||
* \return Number of sections in the ELF file.
|
||||
*/
|
||||
unsigned elf_getNumSections(void *elfFile);
|
||||
|
||||
/**
|
||||
* Determine number of program headers in an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header.
|
||||
*
|
||||
* \return Number of program headers in the ELF file.
|
||||
*/
|
||||
uint16_t elf_getNumProgramHeaders(void *elfFile);
|
||||
|
||||
/**
|
||||
* Return the base physical address of given program header in an ELF file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The memory size of the specified program header
|
||||
*/
|
||||
uint64_t elf_getProgramHeaderPaddr(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the base virtual address of given program header in an ELF file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The memory size of the specified program header
|
||||
*/
|
||||
uint64_t elf_getProgramHeaderVaddr(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the memory size of a given program header in an ELF file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The memory size of the specified program header
|
||||
*/
|
||||
uint64_t elf_getProgramHeaderMemorySize(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the file size of a given program header in an ELF file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The file size of the specified program header
|
||||
*/
|
||||
uint64_t elf_getProgramHeaderFileSize(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the start offset of he file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The offset of this program header with relation to the start
|
||||
* of the elfFile.
|
||||
*/
|
||||
uint64_t elf_getProgramHeaderOffset(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the flags for a given program header
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The flags of a given program header
|
||||
*/
|
||||
uint32_t elf_getProgramHeaderFlags(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the type for a given program header
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The type of a given program header
|
||||
*/
|
||||
uint32_t elf_getProgramHeaderType(void *elfFile, uint16_t ph);
|
||||
|
||||
/**
|
||||
* Return the physical translation of a physical address, with respect
|
||||
* to a given program header
|
||||
*
|
||||
*/
|
||||
uint64_t elf_vtopProgramHeader(void *elfFile, uint16_t ph, uint64_t vaddr);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* \return true if the address in in this program header
|
||||
*/
|
||||
bool elf_vaddrInProgramHeader(void *elfFile, uint16_t ph, uint64_t vaddr);
|
||||
|
||||
/**
|
||||
* Determine the memory bounds of an ELF file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param phys If true return bounds of physical memory, otherwise return
|
||||
* bounds of virtual memory
|
||||
* @param min Pointer to return value of the minimum
|
||||
* @param max Pointer to return value of the maximum
|
||||
*
|
||||
* \return true on success. false on failure, if for example, it is an invalid ELF file
|
||||
*/
|
||||
bool elf_getMemoryBounds(void *elfFile, bool phys, uint64_t *min, uint64_t *max);
|
||||
|
||||
/**
|
||||
* Find the entry point of an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
*
|
||||
* \return The entry point address as a 64-bit integer.
|
||||
*/
|
||||
uint64_t elf_getEntryPoint(void *elfFile);
|
||||
|
||||
/**
|
||||
* Load an ELF file into memory
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF file
|
||||
* @param phys If true load using the physical address, otherwise using the virtual addresses
|
||||
*
|
||||
* \return true on success, false on failure.
|
||||
*
|
||||
* The function assumes that the ELF file is loaded in memory at some
|
||||
* address different to the target address at which it will be loaded.
|
||||
* It also assumes direct access to the source and destination address, i.e:
|
||||
* Memory must be ale to me loaded with a simple memcpy.
|
||||
*
|
||||
* Obviously this also means that if we are loading a 64bit ELF on a 32bit
|
||||
* platform, we assume that any memory address are within the first 4GB.
|
||||
*
|
||||
*/
|
||||
bool elf_loadFile(void *elfFile, bool phys);
|
||||
|
||||
char *elf_getStringTable(void *elfFile, int string_segment);
|
||||
char *elf_getSegmentStringTable(void *elfFile);
|
||||
void *elf_getSectionNamed(void *elfFile, char *str);
|
||||
char *elf_getSectionName(void *elfFile, int i);
|
||||
uint64_t elf_getSectionSize(void *elfFile, int i);
|
||||
uint64_t elf_getSectionLink(void *elfFile, int i);
|
||||
uint64_t elf_getSectionAddr(void *elfFile, int i);
|
||||
|
||||
/**
|
||||
* Return the flags for a given sections
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param i Index of the sections
|
||||
*
|
||||
* \return The flags of a given section
|
||||
*/
|
||||
uint32_t elf_getSectionFlags(void *elfFile, int i);
|
||||
|
||||
/**
|
||||
* Return the type for a given sections
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF header
|
||||
* @param i Index of the sections
|
||||
*
|
||||
* \return The type of a given section
|
||||
*/
|
||||
uint32_t elf_getSectionType(void *elfFile, int i);
|
||||
|
||||
void *elf_getSection(void *elfFile, int i);
|
||||
void elf_getProgramHeaderInfo(void *elfFile, uint16_t ph, uint64_t *p_vaddr,
|
||||
uint64_t *p_paddr, uint64_t *p_filesz,
|
||||
uint64_t *p_offset, uint64_t *p_memsz);
|
||||
|
||||
|
||||
/**
|
||||
* output the details of an ELF file to the stream f
|
||||
*/
|
||||
void elf_fprintf(FILE *f, void *elfFile, int size, const char *name, int flags);
|
||||
|
||||
#define SHT_DYNSYM 0xB
|
||||
#if 0
|
||||
/*
|
||||
* Returns a pointer to the program segment table, which is an array of
|
||||
* ELF64_Phdr_t structs. The size of the array can be found by calling
|
||||
* getNumProgramSegments.
|
||||
*/
|
||||
struct Elf32_Phdr *elf_getProgramSegmentTable(void *elfFile);
|
||||
#endif
|
||||
#if 0
|
||||
/**
|
||||
* Returns a pointer to the program segment table, which is an array of
|
||||
* ELF64_Phdr_t structs. The size of the array can be found by calling
|
||||
* getNumProgramSegments.
|
||||
*/
|
||||
struct Elf32_Shdr *elf_getSectionTable(void *elfFile);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,329 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
#include "elf.h"
|
||||
#include "debug.h"
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int
|
||||
elf32_checkFile(struct Elf32_Header *file)
|
||||
{
|
||||
if (file->e_ident[EI_MAG0] != ELFMAG0
|
||||
|| file->e_ident[EI_MAG1] != ELFMAG1
|
||||
|| file->e_ident[EI_MAG2] != ELFMAG2
|
||||
|| file->e_ident[EI_MAG3] != ELFMAG3)
|
||||
return -1; /* not an elf file */
|
||||
if (file->e_ident[EI_CLASS] != ELFCLASS32)
|
||||
return -2; /* not 32-bit file */
|
||||
return 0; /* elf file looks OK */
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of program segments in this elf file.
|
||||
*/
|
||||
unsigned
|
||||
elf32_getNumSections(struct Elf32_Header *elfFile)
|
||||
{
|
||||
return elfFile->e_shnum;
|
||||
}
|
||||
|
||||
char *
|
||||
elf32_getStringTable(struct Elf32_Header *elfFile)
|
||||
{
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
return (char *)elfFile + sections[elfFile->e_shstrndx].sh_offset;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the program segment table, which is an array of
|
||||
* ELF32_Phdr_t structs. The size of the array can be found by calling
|
||||
* getNumProgramSegments. */
|
||||
struct Elf32_Phdr *
|
||||
elf32_getProgramSegmentTable(struct Elf32_Header *elfFile)
|
||||
{
|
||||
struct Elf32_Header *fileHdr = elfFile;
|
||||
return (struct Elf32_Phdr *) (fileHdr->e_phoff + (size_t) elfFile);
|
||||
}
|
||||
|
||||
/* Returns the number of program segments in this elf file. */
|
||||
uint16_t
|
||||
elf32_getNumProgramHeaders(struct Elf32_Header *elfFile)
|
||||
{
|
||||
struct Elf32_Header *fileHdr = elfFile;
|
||||
return fileHdr->e_phnum;
|
||||
}
|
||||
|
||||
char *
|
||||
elf32_getSectionName(struct Elf32_Header *elfFile, int i)
|
||||
{
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
char *str_table = elf32_getSegmentStringTable(elfFile);
|
||||
if (str_table == NULL) {
|
||||
return "<corrupted>";
|
||||
} else {
|
||||
return str_table + sections[i].sh_name;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf32_getSectionSize(struct Elf32_Header *elfFile, int i)
|
||||
{
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
return sections[i].sh_size;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf32_getSectionLink(struct Elf32_Header *elfFile, int i)
|
||||
{
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
return sections[i].sh_link;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf32_getSectionAddr(struct Elf32_Header *elfFile, int i)
|
||||
{
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
return sections[i].sh_addr;
|
||||
}
|
||||
|
||||
void *
|
||||
elf32_getSection(struct Elf32_Header *elfFile, int i)
|
||||
{
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
return (char *)elfFile + sections[i].sh_offset;
|
||||
}
|
||||
|
||||
void *
|
||||
elf32_getSectionNamed(struct Elf32_Header *elfFile, char *str)
|
||||
{
|
||||
int numSections = elf32_getNumSections(elfFile);
|
||||
int i;
|
||||
for (i = 0; i < numSections; i++) {
|
||||
if (strcmp(str, elf32_getSectionName(elfFile, i)) == 0) {
|
||||
return elf32_getSection(elfFile, i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
elf32_getSegmentStringTable(struct Elf32_Header *elfFile)
|
||||
{
|
||||
struct Elf32_Header *fileHdr = (struct Elf32_Header *) elfFile;
|
||||
if (fileHdr->e_shstrndx == 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
return elf32_getStringTable(elfFile);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ELF_DEBUG
|
||||
void
|
||||
elf32_printStringTable(struct Elf32_Header *elfFile)
|
||||
{
|
||||
int counter;
|
||||
struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
|
||||
char * stringTable;
|
||||
|
||||
if (!sections) {
|
||||
printf("No sections.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
stringTable = ((void *)elfFile) + sections[elfFile->e_shstrndx].sh_offset;
|
||||
|
||||
printf("File is %p; sections is %p; string table is %p\n", elfFile, sections, stringTable);
|
||||
|
||||
for (counter=0; counter < sections[elfFile->e_shstrndx].sh_size; counter++) {
|
||||
printf("%02x %c ", stringTable[counter],
|
||||
stringTable[counter] >= 0x20 ? stringTable[counter] : '.');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
elf32_getSegmentType (struct Elf32_Header *elfFile, int segment)
|
||||
{
|
||||
return elf32_getProgramSegmentTable(elfFile)[segment].p_type;
|
||||
}
|
||||
|
||||
void
|
||||
elf32_getSegmentInfo(struct Elf32_Header *elfFile, int segment, uint64_t *p_vaddr, uint64_t *p_addr, uint64_t *p_filesz, uint64_t *p_offset, uint64_t *p_memsz)
|
||||
{
|
||||
struct Elf32_Phdr *segments;
|
||||
|
||||
segments = elf32_getProgramSegmentTable(elfFile);
|
||||
*p_addr = segments[segment].p_paddr;
|
||||
*p_vaddr = segments[segment].p_vaddr;
|
||||
*p_filesz = segments[segment].p_filesz;
|
||||
*p_offset = segments[segment].p_offset;
|
||||
*p_memsz = segments[segment].p_memsz;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
elf32_getEntryPoint (struct Elf32_Header *elfFile)
|
||||
{
|
||||
return elfFile->e_entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* prints out some details of one elf file
|
||||
*/
|
||||
void
|
||||
elf32_fprintf(FILE *f, struct Elf32_Header *file, int size, const char *name, int flags)
|
||||
{
|
||||
struct Elf32_Phdr *segments;
|
||||
unsigned numSegments;
|
||||
struct Elf32_Shdr *sections;
|
||||
unsigned numSections;
|
||||
int i, r;
|
||||
char *str_table;
|
||||
|
||||
fprintf(f, "Found an elf32 file called \"%s\" located "
|
||||
"at address 0x%p\n", name, file);
|
||||
|
||||
if ((r = elf32_checkFile(file)) != 0) {
|
||||
char *magic = (char*) file;
|
||||
fprintf(f, "Invalid elf file (%d)\n", r);
|
||||
fprintf(f, "Magic is: %2.2hhx %2.2hhx %2.2hhx %2.2hhx\n",
|
||||
magic[0], magic[1], magic[2], magic[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get a pointer to the table of program segments
|
||||
*/
|
||||
segments = elf32_getProgramHeaderTable(file);
|
||||
numSegments = elf32_getNumProgramHeaders(file);
|
||||
|
||||
sections = elf32_getSectionTable(file);
|
||||
numSections = elf32_getNumSections(file);
|
||||
|
||||
if ((uintptr_t) sections > ((uintptr_t) file + size)) {
|
||||
fprintf(f, "Corrupted elfFile..\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* print out info about each section
|
||||
*/
|
||||
|
||||
if (flags & ELF_PRINT_PROGRAM_HEADERS) {
|
||||
/*
|
||||
* print out info about each program segment
|
||||
*/
|
||||
fprintf(f, "Program Headers:\n");
|
||||
fprintf(f, " Type Offset VirtAddr PhysAddr "
|
||||
"FileSiz MemSiz Flg Align\n");
|
||||
for (i = 0; i < numSegments; i++) {
|
||||
if (segments[i].p_type != 1) {
|
||||
fprintf(f, "segment %d is not loadable, "
|
||||
"skipping\n", i);
|
||||
} else {
|
||||
fprintf(f, " LOAD 0x%06d 0x%08d 0x%08d 0x%05d 0x%05d %c%c%c 0x%04d\n",
|
||||
segments[i].p_offset, segments[i].p_vaddr,
|
||||
segments[i].p_paddr,
|
||||
segments[i].p_filesz, segments[i].p_memsz,
|
||||
(segments[i].p_flags & PF_R) ? 'R' : ' ',
|
||||
(segments[i].p_flags & PF_W) ? 'W' : ' ',
|
||||
(segments[i].p_flags & PF_X) ? 'E' : ' ',
|
||||
segments[i].p_align);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags & ELF_PRINT_SECTIONS) {
|
||||
str_table = elf32_getSegmentStringTable(file);
|
||||
|
||||
printf("Section Headers:\n");
|
||||
printf(" [Nr] Name Type Addr Off\n");
|
||||
for (i = 0; i < numSections; i++) {
|
||||
//if (elf_checkSection(file, i) == 0) {
|
||||
fprintf(f, "[%2d] %s %x %x\n", i, elf32_getSectionName(file, i),
|
||||
//fprintf(f, "[%2d] %-17.17s %-15.15s %x %x\n", i, elf32_getSectionName(file, i), " ",
|
||||
///fprintf(f, "%-17.17s %-15.15s %08x %06x\n", elf32_getSectionName(file, i), " " /* sections[i].sh_type
|
||||
// */ ,
|
||||
sections[i].sh_addr, sections[i].sh_offset);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
#ifndef __ELF_ELF_32_H__
|
||||
#define __ELF_ELF_32_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* File header
|
||||
*/
|
||||
struct Elf32_Header {
|
||||
unsigned char e_ident[16];
|
||||
uint16_t e_type; /* Relocatable=1, Executable=2 (+ some
|
||||
* more ..) */
|
||||
uint16_t e_machine; /* Target architecture: MIPS=8 */
|
||||
uint32_t e_version; /* Elf version (should be 1) */
|
||||
uint32_t e_entry; /* Code entry point */
|
||||
uint32_t e_phoff; /* Program header table */
|
||||
uint32_t e_shoff; /* Section header table */
|
||||
uint32_t e_flags; /* Flags */
|
||||
uint16_t e_ehsize; /* ELF header size */
|
||||
uint16_t e_phentsize; /* Size of one program segment
|
||||
* header */
|
||||
uint16_t e_phnum; /* Number of program segment
|
||||
* headers */
|
||||
uint16_t e_shentsize; /* Size of one section header */
|
||||
uint16_t e_shnum; /* Number of section headers */
|
||||
uint16_t e_shstrndx; /* Section header index of the
|
||||
* string table for section header
|
||||
* * names */
|
||||
};
|
||||
|
||||
/*
|
||||
* Section header
|
||||
*/
|
||||
struct Elf32_Shdr {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint32_t sh_flags;
|
||||
uint32_t sh_addr;
|
||||
uint32_t sh_offset;
|
||||
uint32_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint32_t sh_addralign;
|
||||
uint32_t sh_entsize;
|
||||
};
|
||||
|
||||
/*
|
||||
* Program header
|
||||
*/
|
||||
struct Elf32_Phdr {
|
||||
uint32_t p_type; /* Segment type: Loadable segment = 1 */
|
||||
uint32_t p_offset; /* Offset of segment in file */
|
||||
uint32_t p_vaddr; /* Reqd virtual address of segment
|
||||
* when loading */
|
||||
uint32_t p_paddr; /* Reqd physical address of
|
||||
* segment (ignore) */
|
||||
uint32_t p_filesz; /* How many bytes this segment
|
||||
* occupies in file */
|
||||
uint32_t p_memsz; /* How many bytes this segment
|
||||
* should occupy in * memory (when
|
||||
* * loading, expand the segment
|
||||
* by * concatenating enough zero
|
||||
* bytes to it) */
|
||||
uint32_t p_flags; /* Flags: logical "or" of PF_
|
||||
* constants below */
|
||||
uint32_t p_align; /* Reqd alignment of segment in
|
||||
* memory */
|
||||
};
|
||||
|
||||
int elf32_checkFile(struct Elf32_Header *file);
|
||||
struct Elf32_Phdr * elf32_getProgramSegmentTable(struct Elf32_Header *file);
|
||||
unsigned elf32_getNumSections(struct Elf32_Header *file);
|
||||
char * elf32_getStringTable(struct Elf32_Header *file);
|
||||
char * elf32_getSegmentStringTable(struct Elf32_Header *file);
|
||||
|
||||
static inline struct Elf32_Shdr *
|
||||
elf32_getSectionTable(struct Elf32_Header *file)
|
||||
{
|
||||
/* Cast heaven! */
|
||||
return (struct Elf32_Shdr*) (uintptr_t) (((uintptr_t) file) + file->e_shoff);
|
||||
}
|
||||
|
||||
/* accessor functions */
|
||||
static inline uint32_t
|
||||
elf32_getSectionType(struct Elf32_Header *file, uint16_t s)
|
||||
{
|
||||
return elf32_getSectionTable(file)[s].sh_type;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getSectionFlags(struct Elf32_Header *file, uint16_t s)
|
||||
{
|
||||
return elf32_getSectionTable(file)[s].sh_flags;
|
||||
}
|
||||
|
||||
char * elf32_getSectionName(struct Elf32_Header *file, int i);
|
||||
uint32_t elf32_getSectionSize(struct Elf32_Header *file, int i);
|
||||
uint32_t elf32_getSectionLink(struct Elf32_Header *elfFile, int i);
|
||||
uint32_t elf32_getSectionAddr(struct Elf32_Header *elfFile, int i);
|
||||
void * elf32_getSection(struct Elf32_Header *file, int i);
|
||||
void * elf32_getSectionNamed(struct Elf32_Header *file, char *str);
|
||||
int elf32_getSegmentType (struct Elf32_Header *file, int segment);
|
||||
void elf32_getSegmentInfo(struct Elf32_Header *file, int segment, uint64_t *p_vaddr,
|
||||
uint64_t *p_paddr, uint64_t *p_filesz,
|
||||
uint64_t *p_offset, uint64_t *p_memsz);
|
||||
uint32_t elf32_getEntryPoint (struct Elf32_Header *file);
|
||||
|
||||
/* Program header functions */
|
||||
uint16_t elf32_getNumProgramHeaders(struct Elf32_Header *file);
|
||||
|
||||
static inline struct Elf32_Phdr *
|
||||
elf32_getProgramHeaderTable(struct Elf32_Header *file)
|
||||
{
|
||||
/* Cast heaven! */
|
||||
return (struct Elf32_Phdr*) (uintptr_t) (((uintptr_t) file) + file->e_phoff);
|
||||
}
|
||||
|
||||
/* accessor functions */
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderFlags(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_flags;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderType(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_type;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderFileSize(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_filesz;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderMemorySize(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_memsz;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderVaddr(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_vaddr;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderPaddr(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_paddr;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf32_getProgramHeaderOffset(struct Elf32_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_offset;
|
||||
}
|
||||
|
||||
#endif /* __ELF_ELF_32_H__ */
|
||||
@@ -1,321 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
#include "elf.h"
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
elf64_checkFile(void *elfFile)
|
||||
{
|
||||
struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile;
|
||||
if (fileHdr->e_ident[EI_MAG0] != ELFMAG0
|
||||
|| fileHdr->e_ident[EI_MAG1] != ELFMAG1
|
||||
|| fileHdr->e_ident[EI_MAG2] != ELFMAG2
|
||||
|| fileHdr->e_ident[EI_MAG3] != ELFMAG3)
|
||||
return -1; /* not an elf file */
|
||||
if (fileHdr->e_ident[EI_CLASS] != ELFCLASS64)
|
||||
return -2; /* not 64-bit file */
|
||||
#if 0
|
||||
if (fileHdr->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
return -3; /* not big-endian file */
|
||||
if (fileHdr->e_ident[EI_VERSION] != 1)
|
||||
return -4; /* wrong version of elf */
|
||||
if (fileHdr->e_machine != 8)
|
||||
return -5; /* wrong architecture (not MIPS) */
|
||||
if (fileHdr->e_type != 2)
|
||||
return -6; /* not an executable program */
|
||||
if (fileHdr->e_phentsize != sizeof(struct Elf64_Phdr))
|
||||
return -7; /* unexpected size of program segment
|
||||
* header */
|
||||
if (fileHdr->e_phnum == 0)
|
||||
return -8; /* no program segments */
|
||||
if ((fileHdr->e_flags & 0x7e) != 0)
|
||||
return -9; /* wrong flags (did you forgot to compile
|
||||
* with -mno-abicalls?) */
|
||||
#endif
|
||||
return 0; /* elf file looks OK */
|
||||
}
|
||||
|
||||
struct Elf64_Phdr *
|
||||
elf64_getProgramSegmentTable(void *elfFile)
|
||||
/*
|
||||
* Returns a pointer to the program segment table, which is an array of
|
||||
* ELF64_Phdr_t structs. The size of the array can be found by calling
|
||||
* getNumProgramSegments.
|
||||
*/
|
||||
{
|
||||
struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile;
|
||||
return (struct Elf64_Phdr *) ((size_t)fileHdr->e_phoff + (size_t) elfFile);
|
||||
}
|
||||
|
||||
unsigned
|
||||
elf64_getNumSections(void *elfFile)
|
||||
/*
|
||||
* Returns the number of program segments in this elf file.
|
||||
*/
|
||||
{
|
||||
struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile;
|
||||
return fileHdr->e_shnum;
|
||||
}
|
||||
|
||||
char *
|
||||
elf64_getStringTable(void *elfFile, int string_segment)
|
||||
{
|
||||
struct Elf64_Shdr *sections = elf64_getSectionTable((Elf64_Header*)elfFile);
|
||||
return (char *) elfFile + sections[string_segment].sh_offset;
|
||||
}
|
||||
|
||||
char *
|
||||
elf64_getSegmentStringTable(void *elfFile)
|
||||
{
|
||||
struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile;
|
||||
if (fileHdr->e_shstrndx == 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
return elf64_getStringTable(elfFile, fileHdr->e_shstrndx);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
elf64_getSectionName(void *elfFile, int i)
|
||||
{
|
||||
struct Elf64_Shdr *sections = elf64_getSectionTable((Elf64_Header*)elfFile);
|
||||
char *str_table = elf64_getSegmentStringTable((Elf64_Header*)elfFile);
|
||||
if (str_table == NULL) {
|
||||
return (char*)"<corrupted>";
|
||||
} else {
|
||||
return str_table + sections[i].sh_name;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf64_getSectionSize(void *elfFile, int i)
|
||||
{
|
||||
struct Elf64_Shdr *sections = elf64_getSectionTable((Elf64_Header*)elfFile);
|
||||
return sections[i].sh_size;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf64_getSectionAddr(struct Elf64_Header *elfFile, int i)
|
||||
{
|
||||
struct Elf64_Shdr *sections = elf64_getSectionTable(elfFile);
|
||||
return sections[i].sh_addr;
|
||||
}
|
||||
|
||||
void *
|
||||
elf64_getSection(void *elfFile, int i)
|
||||
{
|
||||
struct Elf64_Shdr *sections = elf64_getSectionTable((Elf64_Header*)elfFile);
|
||||
return (char *)elfFile + sections[i].sh_offset;
|
||||
}
|
||||
|
||||
void *
|
||||
elf64_getSectionNamed(void *elfFile, char *str)
|
||||
{
|
||||
int numSections = elf64_getNumSections(elfFile);
|
||||
int i;
|
||||
for (i = 0; i < numSections; i++) {
|
||||
if (strcmp(str, elf64_getSectionName(elfFile, i)) == 0) {
|
||||
return elf64_getSection(elfFile, i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
elf64_getNumProgramHeaders(struct Elf64_Header *elfFile)
|
||||
{
|
||||
return elfFile->e_phnum;
|
||||
}
|
||||
|
||||
int
|
||||
elf64_getSegmentType (void *elfFile, int segment)
|
||||
{
|
||||
return elf64_getProgramSegmentTable(elfFile)[segment].p_type;
|
||||
}
|
||||
|
||||
void
|
||||
elf64_getSegmentInfo(void *elfFile, int segment, uint64_t *p_vaddr,
|
||||
uint64_t *p_paddr, uint64_t *p_filesz, uint64_t *p_offset,
|
||||
uint64_t *p_memsz)
|
||||
{
|
||||
struct Elf64_Phdr *segments;
|
||||
|
||||
segments = elf64_getProgramSegmentTable(elfFile);
|
||||
*p_vaddr = segments[segment].p_vaddr;
|
||||
*p_paddr = segments[segment].p_paddr;
|
||||
*p_filesz = segments[segment].p_filesz;
|
||||
*p_offset = segments[segment].p_offset;
|
||||
*p_memsz = segments[segment].p_memsz;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
elf64_getEntryPoint (struct Elf64_Header *elfFile)
|
||||
{
|
||||
return elfFile->e_entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging functions
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* prints out some details of one elf file
|
||||
*/
|
||||
void
|
||||
elf64_showDetails(void *elfFile, int size, char *name)
|
||||
{
|
||||
struct Elf64_Phdr *segments;
|
||||
unsigned numSegments;
|
||||
struct Elf64_Shdr *sections;
|
||||
unsigned numSections;
|
||||
int i,
|
||||
r;
|
||||
char *str_table;
|
||||
|
||||
printf("Found an elf64 file called \"%s\" located "
|
||||
"at address 0x%lx\n", name, elfFile);
|
||||
|
||||
if ((r = elf64_checkFile(elfFile)) != 0) {
|
||||
char *magic = elfFile;
|
||||
printf("Invalid elf file (%d)\n", r);
|
||||
printf("Magic is: %02.2hhx %02.2hhx %02.2hhx %02.2hhx\n",
|
||||
magic[0], magic[1], magic[2], magic[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
str_table = elf64_getSegmentStringTable(elfFile);
|
||||
|
||||
printf("Got str_table... %p\n", str_table);
|
||||
|
||||
/*
|
||||
* get a pointer to the table of program segments
|
||||
*/
|
||||
segments = elf64_getProgramSegmentTable(elfFile);
|
||||
numSegments = elf64_getNumProgramSegments(elfFile);
|
||||
|
||||
sections = elf64_getSectionTable(elfFile);
|
||||
numSections = elf64_getNumSections(elfFile);
|
||||
|
||||
if ((void *) sections > (void *) elfFile + size ||
|
||||
(((uintptr_t) sections & 0xf) != 0)) {
|
||||
printf("Corrupted elfFile..\n");
|
||||
return;
|
||||
}
|
||||
printf("Sections: %p\n", sections);
|
||||
/*
|
||||
* print out info about each section
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* print out info about each program segment
|
||||
*/
|
||||
printf("Program Headers:\n");
|
||||
printf(" Type Offset VirtAddr PhysAddr "
|
||||
"FileSiz MemSiz Flg Align\n");
|
||||
for (i = 0; i < numSegments; i++) {
|
||||
|
||||
if (segments[i].p_type != 1) {
|
||||
printf("segment %d is not loadable, "
|
||||
"skipping\n", i);
|
||||
} else {
|
||||
printf(" LOAD 0x%06lx 0x%08lx 0x%08lx"
|
||||
" 0x%05lx 0x%05lx %c%c%c 0x%04lx\n",
|
||||
segments[i].p_offset, segments[i].p_vaddr,
|
||||
segments[i].p_vaddr,
|
||||
segments[i].p_filesz, segments[i].p_memsz,
|
||||
segments[i].p_flags & PF_R ? 'R' : ' ',
|
||||
segments[i].p_flags & PF_W ? 'W' : ' ',
|
||||
segments[i].p_flags & PF_X ? 'E' : ' ',
|
||||
segments[i].p_align);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Section Headers:\n");
|
||||
printf(" [Nr] Name Type Addr Off\n");
|
||||
for (i = 0; i < numSections; i++) {
|
||||
if (elf_checkSection(elfFile, i) == 0) {
|
||||
printf("%-17.17s %-15.15s %08x %06x\n", elf64_getSectionName(elfFile, i), " " /* sections[i].sh_type
|
||||
*/ ,
|
||||
sections[i].sh_addr, sections[i].sh_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Australian Public Licence B (OZPLB)
|
||||
*
|
||||
* Version 1-0
|
||||
*
|
||||
* Copyright (c) 2004 University of New South Wales
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Developed by: Operating Systems and Distributed Systems Group (DiSy)
|
||||
* University of New South Wales
|
||||
* http://www.disy.cse.unsw.edu.au
|
||||
*
|
||||
* Permission is granted by University of New South Wales, free of charge, to
|
||||
* any person obtaining a copy of this software and any associated
|
||||
* documentation files (the "Software") to deal with the Software without
|
||||
* restriction, including (without limitation) the rights to use, copy,
|
||||
* modify, adapt, merge, publish, distribute, communicate to the public,
|
||||
* sublicense, and/or sell, lend or rent out copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject
|
||||
* to the following conditions:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimers.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimers in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* * Neither the name of University of New South Wales, nor the names of its
|
||||
* contributors, may be used to endorse or promote products derived
|
||||
* from this Software without specific prior written permission.
|
||||
*
|
||||
* EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT
|
||||
* PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND
|
||||
* NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS,
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS
|
||||
* REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE,
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT,
|
||||
* THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF
|
||||
* ERRORS, WHETHER OR NOT DISCOVERABLE.
|
||||
*
|
||||
* TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
* NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL
|
||||
* THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER
|
||||
* LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR
|
||||
* OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS
|
||||
* OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR
|
||||
* OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT,
|
||||
* CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER
|
||||
* DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS
|
||||
* CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS,
|
||||
* DAMAGES OR OTHER LIABILITY.
|
||||
*
|
||||
* If applicable legislation implies representations, warranties, or
|
||||
* conditions, or imposes obligations or liability on University of New South
|
||||
* Wales or one of its contributors in respect of the Software that
|
||||
* cannot be wholly or partly excluded, restricted or modified, the
|
||||
* liability of University of New South Wales or the contributor is limited, to
|
||||
* the full extent permitted by the applicable legislation, at its
|
||||
* option, to:
|
||||
* a. in the case of goods, any one or more of the following:
|
||||
* i. the replacement of the goods or the supply of equivalent goods;
|
||||
* ii. the repair of the goods;
|
||||
* iii. the payment of the cost of replacing the goods or of acquiring
|
||||
* equivalent goods;
|
||||
* iv. the payment of the cost of having the goods repaired; or
|
||||
* b. in the case of services:
|
||||
* i. the supplying of the services again; or
|
||||
* ii. the payment of the cost of having the services supplied again.
|
||||
*
|
||||
* The construction, validity and performance of this licence is governed
|
||||
* by the laws in force in New South Wales, Australia.
|
||||
*/
|
||||
#ifndef __LIBELF_64_H__
|
||||
#define __LIBELF_64_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* File header
|
||||
*/
|
||||
struct Elf64_Header {
|
||||
unsigned char e_ident[16];
|
||||
uint16_t e_type; /* Relocatable=1, Executable=2 (+ some
|
||||
* more ..) */
|
||||
uint16_t e_machine; /* Target architecture: MIPS=8 */
|
||||
uint32_t e_version; /* Elf version (should be 1) */
|
||||
uint64_t e_entry; /* Code entry point */
|
||||
uint64_t e_phoff; /* Program header table */
|
||||
uint64_t e_shoff; /* Section header table */
|
||||
uint32_t e_flags; /* Flags */
|
||||
uint16_t e_ehsize; /* ELF header size */
|
||||
uint16_t e_phentsize; /* Size of one program segment
|
||||
* header */
|
||||
uint16_t e_phnum; /* Number of program segment
|
||||
* headers */
|
||||
uint16_t e_shentsize; /* Size of one section header */
|
||||
uint16_t e_shnum; /* Number of section headers */
|
||||
uint16_t e_shstrndx; /* Section header index of the
|
||||
* string table for section header
|
||||
* * names */
|
||||
};
|
||||
|
||||
/*
|
||||
* Section header
|
||||
*/
|
||||
struct Elf64_Shdr {
|
||||
uint32_t sh_name;
|
||||
uint32_t sh_type;
|
||||
uint64_t sh_flags;
|
||||
uint64_t sh_addr;
|
||||
uint64_t sh_offset;
|
||||
uint64_t sh_size;
|
||||
uint32_t sh_link;
|
||||
uint32_t sh_info;
|
||||
uint64_t sh_addralign;
|
||||
uint64_t sh_entsize;
|
||||
};
|
||||
|
||||
/*
|
||||
* Program header
|
||||
*/
|
||||
struct Elf64_Phdr {
|
||||
uint32_t p_type; /* Segment type: Loadable segment = 1 */
|
||||
uint32_t p_flags; /* Flags: logical "or" of PF_
|
||||
* constants below */
|
||||
uint64_t p_offset; /* Offset of segment in file */
|
||||
uint64_t p_vaddr; /* Reqd virtual address of segment
|
||||
* when loading */
|
||||
uint64_t p_paddr; /* Reqd physical address of
|
||||
* segment */
|
||||
uint64_t p_filesz; /* How many bytes this segment
|
||||
* occupies in file */
|
||||
uint64_t p_memsz; /* How many bytes this segment
|
||||
* should occupy in * memory (when
|
||||
* * loading, expand the segment
|
||||
* by * concatenating enough zero
|
||||
* bytes to it) */
|
||||
uint64_t p_align; /* Reqd alignment of segment in
|
||||
* memory */
|
||||
};
|
||||
|
||||
int elf64_checkFile(void *elfFile);
|
||||
struct Elf64_Phdr * elf64_getProgramSegmentTable(void *elfFile);
|
||||
unsigned elf64_getNumSections(void *elfFile);
|
||||
char * elf64_getStringTable(void *elfFile, int string_segment);
|
||||
char * elf64_getSegmentStringTable(void *elfFile);
|
||||
|
||||
static inline struct Elf64_Shdr *
|
||||
elf64_getSectionTable(struct Elf64_Header *file)
|
||||
{
|
||||
/* Cast heaven! */
|
||||
return (struct Elf64_Shdr*) (uintptr_t) (((uintptr_t) file) + file->e_shoff);
|
||||
}
|
||||
|
||||
/* accessor functions */
|
||||
static inline uint32_t
|
||||
elf64_getSectionType(struct Elf64_Header *file, uint16_t s)
|
||||
{
|
||||
return elf64_getSectionTable(file)[s].sh_type;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t elf64_getSectionLink(struct Elf64_Header *file, int s)
|
||||
{
|
||||
return elf64_getSectionTable(file)[s].sh_link;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf64_getSectionFlags(struct Elf64_Header *file, uint16_t s)
|
||||
{
|
||||
return elf64_getSectionTable(file)[s].sh_flags;
|
||||
}
|
||||
|
||||
char * elf64_getSectionName(void *elfFile, int i);
|
||||
uint64_t elf64_getSectionSize(void *elfFile, int i);
|
||||
uint64_t elf64_getSectionAddr(struct Elf64_Header *elfFile, int i);
|
||||
void * elf64_getSection(void *elfFile, int i);
|
||||
void * elf64_getSectionNamed(void *elfFile, char *str);
|
||||
int elf64_getSegmentType (void *elfFile, int segment);
|
||||
void elf64_getSegmentInfo(void *elfFile, int segment, uint64_t *p_vaddr,
|
||||
uint64_t *p_paddr, uint64_t *p_filesz,
|
||||
uint64_t *p_offset, uint64_t *p_memsz);
|
||||
void elf64_showDetails(void *elfFile, int size, char *name);
|
||||
uint64_t elf64_getEntryPoint (struct Elf64_Header *elfFile);
|
||||
|
||||
/* Program Headers functions */
|
||||
/* Program header functions */
|
||||
uint16_t elf64_getNumProgramHeaders(struct Elf64_Header *file);
|
||||
|
||||
static inline struct Elf64_Phdr *
|
||||
elf64_getProgramHeaderTable(struct Elf64_Header *file)
|
||||
{
|
||||
/* Cast hell! */
|
||||
return (struct Elf64_Phdr*) (uintptr_t) (((uintptr_t) file) + file->e_phoff);
|
||||
}
|
||||
|
||||
/* accessor functions */
|
||||
static inline uint32_t
|
||||
elf64_getProgramHeaderFlags(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_flags;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
elf64_getProgramHeaderType(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_type;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
elf64_getProgramHeaderFileSize(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_filesz;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
elf64_getProgramHeaderMemorySize(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_memsz;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
elf64_getProgramHeaderVaddr(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_vaddr;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
elf64_getProgramHeaderPaddr(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_paddr;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
elf64_getProgramHeaderOffset(struct Elf64_Header *file, uint16_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_offset;
|
||||
}
|
||||
|
||||
#endif /* __LIBELF_64_H__ */
|
||||
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
Authors: Luke Deller, Ben Leslie
|
||||
Created: 24/Sep/1999
|
||||
*/
|
||||
|
||||
/**
|
||||
\file
|
||||
|
||||
\brief Generic ELF library
|
||||
|
||||
The ELF library is designed to make the task of parsing and getting information
|
||||
out of an ELF file easier.
|
||||
|
||||
It provides function to obtain the various different fields in the ELF header, and
|
||||
the program and segment information.
|
||||
|
||||
Also importantly, it provides a function elf_loadFile which will load a given
|
||||
ELF file into memory.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
#include <elf/exec_elf.h>
|
||||
typedef Elf64_Ehdr Elf64_Header;
|
||||
typedef Elf32_Ehdr Elf32_Header;
|
||||
#else
|
||||
#include <elf.h>
|
||||
#endif
|
||||
|
||||
struct elf {
|
||||
void const *elfFile;
|
||||
size_t elfSize;
|
||||
unsigned char elfClass; /* 32-bit or 64-bit */
|
||||
};
|
||||
typedef struct elf elf_t;
|
||||
|
||||
enum elf_addr_type {
|
||||
VIRTUAL,
|
||||
PHYSICAL
|
||||
};
|
||||
typedef enum elf_addr_type elf_addr_type_t;
|
||||
|
||||
/* ELF header functions */
|
||||
/**
|
||||
* Initialises an elf_t structure and checks that the ELF file is valid.
|
||||
* This function must be called to validate the ELF before any other function.
|
||||
* Otherwise, attempting to call other functions with an invalid ELF file may
|
||||
* result in undefined behaviour.
|
||||
*
|
||||
* @param file ELF file to use
|
||||
* @param size Size of the ELF file
|
||||
* @param res elf_t to initialise
|
||||
*
|
||||
* \return 0 on success, otherwise < 0
|
||||
*/
|
||||
int elf_newFile(const void *file, size_t size, elf_t *res);
|
||||
|
||||
/**
|
||||
* Initialises and elf_t structure and checks that the ELF file is valid.
|
||||
* The validity of a potential ELF file can be determined by the arguments
|
||||
* check_pht and check_st.
|
||||
* If both check_pht and check_st are true, this function is equivalent to
|
||||
* elf_newFile.
|
||||
* Calling other functions with an invalid ELF file may result in undefined
|
||||
* behaviour.
|
||||
*
|
||||
* @param file ELF file to use
|
||||
* @param size Size of the ELF file
|
||||
* @param check_pht Whether to check the ELF program header table is valid
|
||||
* @param check_st Whether to check the ELF section table is valid
|
||||
* @param res elf_t to initialise
|
||||
*
|
||||
* \return 0 on success, otherwise < 0
|
||||
*/
|
||||
int elf_newFile_maybe_unsafe(const void *file, size_t size, bool check_pht, bool check_st, elf_t *res);
|
||||
|
||||
/**
|
||||
* Checks that file starts with the ELF magic number.
|
||||
* File must be at least 4 bytes (SELFMAG).
|
||||
*
|
||||
* @param file to check
|
||||
*
|
||||
* \return 0 on success, otherwise < 0
|
||||
*/
|
||||
int elf_check_magic(const char *file);
|
||||
|
||||
/**
|
||||
* Checks that elfFile points to an ELF file with a valid ELF header.
|
||||
*
|
||||
* @param elfFile Potential ELF file to check
|
||||
*
|
||||
* \return 0 on success, otherwise < 0
|
||||
*/
|
||||
int elf_checkFile(elf_t *elfFile);
|
||||
|
||||
/**
|
||||
* Checks that elfFile points to an ELF file with a valid program header table.
|
||||
*
|
||||
* @param elfFile Potential ELF file to check
|
||||
*
|
||||
* \return 0 on success, otherwise < 0
|
||||
*/
|
||||
int elf_checkProgramHeaderTable(const elf_t *elfFile);
|
||||
|
||||
/**
|
||||
* Checks that elfFile points to an ELF file with a valid section table.
|
||||
*
|
||||
* @param elfFile Potential ELF file to check
|
||||
*
|
||||
* \return 0 on success, otherwise < 0
|
||||
*/
|
||||
int elf_checkSectionTable(const elf_t *elfFile);
|
||||
|
||||
/**
|
||||
* Find the entry point of an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
*
|
||||
* \return The entry point address.
|
||||
*/
|
||||
uintptr_t elf_getEntryPoint(const elf_t *elfFile);
|
||||
|
||||
/**
|
||||
* Determine number of program headers in an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure.
|
||||
*
|
||||
* \return Number of program headers in the ELF file.
|
||||
*/
|
||||
size_t elf_getNumProgramHeaders(const elf_t *elfFile);
|
||||
|
||||
/**
|
||||
* Determine number of sections in an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure.
|
||||
*
|
||||
* \return Number of sections in the ELF file.
|
||||
*/
|
||||
size_t elf_getNumSections(const elf_t *elfFile);
|
||||
|
||||
/**
|
||||
* Get the index of the section header string table of an ELF file.
|
||||
*
|
||||
* @param elf Pointer to a valid ELF structure.
|
||||
*
|
||||
* \return The index of the section header string table.
|
||||
*/
|
||||
size_t elf_getSectionStringTableIndex(const elf_t *elf);
|
||||
|
||||
/**
|
||||
* Get a string table section of an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure.
|
||||
* @param string_section The section number of the string table.
|
||||
*
|
||||
* \return The string table, or NULL if the section is not a string table.
|
||||
*/
|
||||
const char *elf_getStringTable(const elf_t *elfFile, size_t string_segment);
|
||||
|
||||
/**
|
||||
* Get the string table for section header names.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure.
|
||||
*
|
||||
* \return The string table, or NULL if there is no table.
|
||||
*/
|
||||
const char *elf_getSectionStringTable(const elf_t *elfFile);
|
||||
|
||||
|
||||
/* Section header functions */
|
||||
/**
|
||||
* Get a section of an ELF file.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i The section number
|
||||
*
|
||||
* \return The section, or NULL if there is no section.
|
||||
*/
|
||||
const void *elf_getSection(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Get the section of an ELF file with a given name.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param str Name of the section
|
||||
* @param i Pointer to store the section number
|
||||
*
|
||||
* \return The section, or NULL if there is no section.
|
||||
*/
|
||||
const void *elf_getSectionNamed(const elf_t *elfFile, const char *str, size_t *i);
|
||||
|
||||
/**
|
||||
* Return the name of a given section.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The name of a given section.
|
||||
*/
|
||||
const char *elf_getSectionName(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the offset to the name of a given section in the section header
|
||||
* string table.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The offset to the name of a given section in the section header
|
||||
* string table.
|
||||
*/
|
||||
size_t elf_getSectionNameOffset(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the type of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The type of a given section.
|
||||
*/
|
||||
uint32_t elf_getSectionType(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the flags of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The flags of a given section.
|
||||
*/
|
||||
size_t elf_getSectionFlags(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the address of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The address of a given section.
|
||||
*/
|
||||
uintptr_t elf_getSectionAddr(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the offset of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The offset of a given section.
|
||||
*/
|
||||
size_t elf_getSectionOffset(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the size of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The size of a given section.
|
||||
*/
|
||||
size_t elf_getSectionSize(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the related section index of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The related section index of a given section.
|
||||
*/
|
||||
uint32_t elf_getSectionLink(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return extra information of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return Extra information of a given section.
|
||||
*/
|
||||
uint32_t elf_getSectionInfo(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the alignment of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The alignment of a given section.
|
||||
*/
|
||||
size_t elf_getSectionAddrAlign(const elf_t *elfFile, size_t i);
|
||||
|
||||
/**
|
||||
* Return the entry size of a given section
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param i Index of the section
|
||||
*
|
||||
* \return The entry size of a given section.
|
||||
*/
|
||||
size_t elf_getSectionEntrySize(const elf_t *elfFile, size_t i);
|
||||
|
||||
|
||||
/* Program header functions */
|
||||
|
||||
/**
|
||||
* Return the segment data for a given program header.
|
||||
*
|
||||
* @param elf Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return Pointer to the segment data
|
||||
*/
|
||||
const void *elf_getProgramSegment(const elf_t *elf, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the type for a given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The type of a given program header.
|
||||
*/
|
||||
uint32_t elf_getProgramHeaderType(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the segment offset for a given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The offset of this program header from the start of the file.
|
||||
*/
|
||||
size_t elf_getProgramHeaderOffset(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the base virtual address of given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The memory size of the specified program header.
|
||||
*/
|
||||
uintptr_t elf_getProgramHeaderVaddr(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the base physical address of given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The memory size of the specified program header.
|
||||
*/
|
||||
uintptr_t elf_getProgramHeaderPaddr(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the file size of a given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The file size of the specified program header.
|
||||
*/
|
||||
size_t elf_getProgramHeaderFileSize(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the memory size of a given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The memory size of the specified program header.
|
||||
*/
|
||||
size_t elf_getProgramHeaderMemorySize(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the flags for a given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The flags of a given program header.
|
||||
*/
|
||||
uint32_t elf_getProgramHeaderFlags(const elf_t *elfFile, size_t ph);
|
||||
|
||||
/**
|
||||
* Return the alignment for a given program header.
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param ph Index of the program header
|
||||
*
|
||||
* \return The alignment of the given program header.
|
||||
*/
|
||||
size_t elf_getProgramHeaderAlign(const elf_t *elfFile, size_t ph);
|
||||
|
||||
|
||||
/* Utility functions */
|
||||
|
||||
/**
|
||||
* Determine the memory bounds of an ELF file
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF structure
|
||||
* @param addr_type If PHYSICAL return bounds of physical memory, otherwise
|
||||
* return bounds of virtual memory
|
||||
* @param min Pointer to return value of the minimum
|
||||
* @param max Pointer to return value of the maximum
|
||||
*
|
||||
* \return true on success. false on failure, if for example, it is an invalid ELF file
|
||||
*/
|
||||
int elf_getMemoryBounds(const elf_t *elfFile, elf_addr_type_t addr_type, uintptr_t *min, uintptr_t *max);
|
||||
|
||||
/**
|
||||
*
|
||||
* \return true if the address in in this program header
|
||||
*/
|
||||
int elf_vaddrInProgramHeader(const elf_t *elfFile, size_t ph, uintptr_t vaddr);
|
||||
|
||||
/**
|
||||
* Return the physical translation of a physical address, with respect
|
||||
* to a given program header
|
||||
*
|
||||
*/
|
||||
uintptr_t elf_vtopProgramHeader(const elf_t *elfFile, size_t ph, uintptr_t vaddr);
|
||||
|
||||
/**
|
||||
* Load an ELF file into memory
|
||||
*
|
||||
* @param elfFile Pointer to a valid ELF file
|
||||
* @param addr_type If PHYSICAL load using the physical address, otherwise using the
|
||||
* virtual addresses
|
||||
*
|
||||
* \return true on success, false on failure.
|
||||
*
|
||||
* The function assumes that the ELF file is loaded in memory at some
|
||||
* address different to the target address at which it will be loaded.
|
||||
* It also assumes direct access to the source and destination address, i.e:
|
||||
* Memory must be able to be loaded with a simple memcpy.
|
||||
*
|
||||
* Obviously this also means that if we are loading a 64bit ELF on a 32bit
|
||||
* platform, we assume that any memory addresses are within the first 4GB.
|
||||
*
|
||||
*/
|
||||
int elf_loadFile(const elf_t *elfFile, elf_addr_type_t addr_type);
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <elf/elf.h>
|
||||
|
||||
/* ELF header functions */
|
||||
int elf32_checkFile(elf_t *elf);
|
||||
|
||||
int elf32_checkProgramHeaderTable(const elf_t *elf);
|
||||
|
||||
int elf32_checkSectionTable(const elf_t *elf);
|
||||
|
||||
static inline bool elf_isElf32(const elf_t *elf)
|
||||
{
|
||||
return elf->elfClass == ELFCLASS32;
|
||||
}
|
||||
|
||||
static inline Elf32_Ehdr elf32_getHeader(const elf_t *elf)
|
||||
{
|
||||
return *(Elf32_Ehdr *) elf->elfFile;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf32_getEntryPoint(const elf_t *elf)
|
||||
{
|
||||
return elf32_getHeader(elf).e_entry;
|
||||
}
|
||||
|
||||
static inline const Elf32_Phdr *elf32_getProgramHeaderTable(const elf_t *file)
|
||||
{
|
||||
return (Elf32_Phdr*) (uintptr_t) ((uintptr_t)(file->elfFile) + elf32_getHeader(file).e_phoff);
|
||||
}
|
||||
|
||||
static inline const Elf32_Shdr *elf32_getSectionTable(const elf_t *elf)
|
||||
{
|
||||
return (Elf32_Shdr*) (uintptr_t) ((uintptr_t)(elf->elfFile) + elf32_getHeader(elf).e_shoff);
|
||||
}
|
||||
|
||||
static inline size_t elf32_getNumProgramHeaders(const elf_t *elf)
|
||||
{
|
||||
return elf32_getHeader(elf).e_phnum;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getNumSections(const elf_t *elf)
|
||||
{
|
||||
return elf32_getHeader(elf).e_shnum;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getSectionStringTableIndex(const elf_t *elf)
|
||||
{
|
||||
return elf32_getHeader(elf).e_shstrndx;
|
||||
}
|
||||
|
||||
|
||||
/* Section header functions */
|
||||
static inline size_t elf32_getSectionNameOffset(const elf_t *elf, size_t s)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[s].sh_name;
|
||||
}
|
||||
|
||||
static inline uint32_t elf32_getSectionType(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_type;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getSectionFlags(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_flags;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf32_getSectionAddr(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_addr;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getSectionOffset(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_offset;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getSectionSize(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_size;
|
||||
}
|
||||
|
||||
static inline uint32_t elf32_getSectionLink(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_link;
|
||||
}
|
||||
|
||||
static inline uint32_t elf32_getSectionInfo(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_info;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getSectionAddrAlign(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_addralign;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getSectionEntrySize(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf32_getSectionTable(elf)[i].sh_entsize;
|
||||
}
|
||||
|
||||
|
||||
/* Program header functions */
|
||||
static inline uint32_t elf32_getProgramHeaderType(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_type;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getProgramHeaderOffset(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_offset;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf32_getProgramHeaderVaddr(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_vaddr;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf32_getProgramHeaderPaddr(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_paddr;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getProgramHeaderFileSize(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_filesz;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getProgramHeaderMemorySize(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_memsz;
|
||||
}
|
||||
|
||||
static inline uint32_t elf32_getProgramHeaderFlags(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_flags;
|
||||
}
|
||||
|
||||
static inline size_t elf32_getProgramHeaderAlign(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf32_getProgramHeaderTable(file)[ph].p_align;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <elf/elf.h>
|
||||
|
||||
/* ELF header functions */
|
||||
int elf64_checkFile(elf_t *elf);
|
||||
|
||||
int elf64_checkProgramHeaderTable(const elf_t *elf);
|
||||
|
||||
int elf64_checkSectionTable(const elf_t *elf);
|
||||
|
||||
static inline bool elf_isElf64(const elf_t *elf)
|
||||
{
|
||||
return elf->elfClass == ELFCLASS64;
|
||||
}
|
||||
|
||||
static inline Elf64_Ehdr elf64_getHeader(const elf_t *elf)
|
||||
{
|
||||
return *(Elf64_Ehdr *) elf->elfFile;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf64_getEntryPoint(const elf_t *file)
|
||||
{
|
||||
return elf64_getHeader(file).e_entry;
|
||||
}
|
||||
|
||||
static inline const Elf64_Phdr *elf64_getProgramHeaderTable(const elf_t *file)
|
||||
{
|
||||
return (Elf64_Phdr*) (uintptr_t) ((uintptr_t)(file->elfFile) + elf64_getHeader(file).e_phoff);
|
||||
}
|
||||
|
||||
static inline const Elf64_Shdr *elf64_getSectionTable(const elf_t *file)
|
||||
{
|
||||
return (Elf64_Shdr*) (uintptr_t) ((uintptr_t)(file->elfFile) + elf64_getHeader(file).e_shoff);
|
||||
}
|
||||
|
||||
static inline size_t elf64_getNumProgramHeaders(const elf_t *file)
|
||||
{
|
||||
return elf64_getHeader(file).e_phnum;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getNumSections(const elf_t *elf)
|
||||
{
|
||||
return elf64_getHeader(elf).e_shnum;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getSectionStringTableIndex(const elf_t *elf)
|
||||
{
|
||||
return elf64_getHeader(elf).e_shstrndx;
|
||||
}
|
||||
|
||||
|
||||
/* Section header functions */
|
||||
static inline size_t elf64_getSectionNameOffset(const elf_t *elf, size_t s)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[s].sh_name;
|
||||
}
|
||||
|
||||
static inline uint32_t elf64_getSectionType(const elf_t *file, size_t s)
|
||||
{
|
||||
return elf64_getSectionTable(file)[s].sh_type;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getSectionFlags(const elf_t *file, size_t s)
|
||||
{
|
||||
return elf64_getSectionTable(file)[s].sh_flags;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf64_getSectionAddr(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_addr;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getSectionOffset(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_offset;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getSectionSize(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_size;
|
||||
}
|
||||
|
||||
static inline uint32_t elf64_getSectionLink(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_link;
|
||||
}
|
||||
|
||||
static inline uint32_t elf64_getSectionInfo(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_info;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getSectionAddrAlign(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_addralign;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getSectionEntrySize(const elf_t *elf, size_t i)
|
||||
{
|
||||
return elf64_getSectionTable(elf)[i].sh_entsize;
|
||||
}
|
||||
|
||||
|
||||
/* Program header functions */
|
||||
static inline uint32_t elf64_getProgramHeaderType(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_type;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getProgramHeaderOffset(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_offset;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf64_getProgramHeaderVaddr(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_vaddr;
|
||||
}
|
||||
|
||||
static inline uintptr_t elf64_getProgramHeaderPaddr(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_paddr;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getProgramHeaderFileSize(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_filesz;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getProgramHeaderMemorySize(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_memsz;
|
||||
}
|
||||
|
||||
static inline uint32_t elf64_getProgramHeaderFlags(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_flags;
|
||||
}
|
||||
|
||||
static inline size_t elf64_getProgramHeaderAlign(const elf_t *file, size_t ph)
|
||||
{
|
||||
return elf64_getProgramHeaderTable(file)[ph].p_align;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,827 @@
|
||||
/* $OpenBSD: exec_elf.h,v 1.97 2022/10/27 23:17:18 deraadt Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995, 1996 Erik Theisen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the ELF ABI header file
|
||||
* formerly known as "elf_abi.h".
|
||||
*/
|
||||
|
||||
#ifndef _SYS_EXEC_ELF_H_
|
||||
#define _SYS_EXEC_ELF_H_
|
||||
|
||||
typedef uint64_t __uint64_t;
|
||||
typedef int64_t __int64_t;
|
||||
typedef uint32_t __uint32_t;
|
||||
typedef int32_t __int32_t;
|
||||
typedef uint16_t __uint16_t;
|
||||
typedef int16_t __int16_t;
|
||||
|
||||
typedef __uint32_t Elf32_Addr; /* Unsigned program address */
|
||||
typedef __uint32_t Elf32_Off; /* Unsigned file offset */
|
||||
typedef __int32_t Elf32_Sword; /* Signed large integer */
|
||||
typedef __uint32_t Elf32_Word; /* Unsigned large integer */
|
||||
typedef __uint16_t Elf32_Half; /* Unsigned medium integer */
|
||||
typedef __uint64_t Elf32_Lword;
|
||||
|
||||
typedef __uint64_t Elf64_Addr;
|
||||
typedef __uint64_t Elf64_Off;
|
||||
typedef __int32_t Elf64_Shalf;
|
||||
|
||||
typedef __int32_t Elf64_Sword;
|
||||
typedef __uint32_t Elf64_Word;
|
||||
|
||||
typedef __int64_t Elf64_Sxword;
|
||||
typedef __uint64_t Elf64_Xword;
|
||||
typedef __uint64_t Elf64_Lword;
|
||||
|
||||
typedef __uint16_t Elf64_Half;
|
||||
|
||||
/*
|
||||
* e_ident[] identification indexes
|
||||
* See http://www.sco.com/developers/gabi/latest/ch4.eheader.html
|
||||
*/
|
||||
#define EI_MAG0 0 /* file ID */
|
||||
#define EI_MAG1 1 /* file ID */
|
||||
#define EI_MAG2 2 /* file ID */
|
||||
#define EI_MAG3 3 /* file ID */
|
||||
#define EI_CLASS 4 /* file class */
|
||||
#define EI_DATA 5 /* data encoding */
|
||||
#define EI_VERSION 6 /* ELF header version */
|
||||
#define EI_OSABI 7 /* OS/ABI ID */
|
||||
#define EI_ABIVERSION 8 /* ABI version */
|
||||
#define EI_PAD 9 /* start of pad bytes */
|
||||
#define EI_NIDENT 16 /* Size of e_ident[] */
|
||||
|
||||
/* e_ident[] magic number */
|
||||
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
|
||||
#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
|
||||
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
|
||||
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
|
||||
#define ELFMAG "\177ELF" /* magic */
|
||||
#define SELFMAG 4 /* size of magic */
|
||||
|
||||
/* e_ident[] file class */
|
||||
#define ELFCLASSNONE 0 /* invalid */
|
||||
#define ELFCLASS32 1 /* 32-bit objs */
|
||||
#define ELFCLASS64 2 /* 64-bit objs */
|
||||
#define ELFCLASSNUM 3 /* number of classes */
|
||||
|
||||
/* e_ident[] data encoding */
|
||||
#define ELFDATANONE 0 /* invalid */
|
||||
#define ELFDATA2LSB 1 /* Little-Endian */
|
||||
#define ELFDATA2MSB 2 /* Big-Endian */
|
||||
#define ELFDATANUM 3 /* number of data encode defines */
|
||||
|
||||
/* e_ident[] Operating System/ABI */
|
||||
#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
|
||||
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
|
||||
#define ELFOSABI_NETBSD 2 /* NetBSD */
|
||||
#define ELFOSABI_LINUX 3 /* GNU/Linux */
|
||||
#define ELFOSABI_HURD 4 /* GNU/Hurd */
|
||||
#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
|
||||
#define ELFOSABI_SOLARIS 6 /* Solaris */
|
||||
#define ELFOSABI_MONTEREY 7 /* Monterey */
|
||||
#define ELFOSABI_IRIX 8 /* IRIX */
|
||||
#define ELFOSABI_FREEBSD 9 /* FreeBSD */
|
||||
#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
|
||||
#define ELFOSABI_MODESTO 11 /* Novell Modesto */
|
||||
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
|
||||
#define ELFOSABI_ARM 97 /* ARM */
|
||||
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
|
||||
|
||||
/* e_ident */
|
||||
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
|
||||
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
|
||||
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
|
||||
(ehdr).e_ident[EI_MAG3] == ELFMAG3)
|
||||
|
||||
/* ELF Header */
|
||||
typedef struct elfhdr {
|
||||
unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
|
||||
Elf32_Half e_type; /* object file type */
|
||||
Elf32_Half e_machine; /* machine */
|
||||
Elf32_Word e_version; /* object file version */
|
||||
Elf32_Addr e_entry; /* virtual entry point */
|
||||
Elf32_Off e_phoff; /* program header table offset */
|
||||
Elf32_Off e_shoff; /* section header table offset */
|
||||
Elf32_Word e_flags; /* processor-specific flags */
|
||||
Elf32_Half e_ehsize; /* ELF header size */
|
||||
Elf32_Half e_phentsize; /* program header entry size */
|
||||
Elf32_Half e_phnum; /* number of program header entries */
|
||||
Elf32_Half e_shentsize; /* section header entry size */
|
||||
Elf32_Half e_shnum; /* number of section header entries */
|
||||
Elf32_Half e_shstrndx; /* section header table's "section
|
||||
header string table" entry offset */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT]; /* Id bytes */
|
||||
Elf64_Half e_type; /* file type */
|
||||
Elf64_Half e_machine; /* machine type */
|
||||
Elf64_Word e_version; /* version number */
|
||||
Elf64_Addr e_entry; /* entry point */
|
||||
Elf64_Off e_phoff; /* Program hdr offset */
|
||||
Elf64_Off e_shoff; /* Section hdr offset */
|
||||
Elf64_Word e_flags; /* Processor flags */
|
||||
Elf64_Half e_ehsize; /* sizeof ehdr */
|
||||
Elf64_Half e_phentsize; /* Program header entry size */
|
||||
Elf64_Half e_phnum; /* Number of program headers */
|
||||
Elf64_Half e_shentsize; /* Section header entry size */
|
||||
Elf64_Half e_shnum; /* Number of section headers */
|
||||
Elf64_Half e_shstrndx; /* String table index */
|
||||
} Elf64_Ehdr;
|
||||
|
||||
/* e_type */
|
||||
#define ET_NONE 0 /* No file type */
|
||||
#define ET_REL 1 /* relocatable file */
|
||||
#define ET_EXEC 2 /* executable file */
|
||||
#define ET_DYN 3 /* shared object file */
|
||||
#define ET_CORE 4 /* core file */
|
||||
#define ET_NUM 5 /* number of types */
|
||||
#define ET_LOPROC 0xff00 /* reserved range for processor */
|
||||
#define ET_HIPROC 0xffff /* specific e_type */
|
||||
|
||||
/* e_machine */
|
||||
#define EM_NONE 0 /* No Machine */
|
||||
#define EM_M32 1 /* AT&T WE 32100 */
|
||||
#define EM_SPARC 2 /* SPARC */
|
||||
#define EM_386 3 /* Intel 80386 */
|
||||
#define EM_68K 4 /* Motorola 68000 */
|
||||
#define EM_88K 5 /* Motorola 88000 */
|
||||
#define EM_486 6 /* Intel 80486 - unused? */
|
||||
#define EM_860 7 /* Intel 80860 */
|
||||
#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
|
||||
/*
|
||||
* Don't know if EM_MIPS_RS4_BE,
|
||||
* EM_SPARC64, EM_PARISC,
|
||||
* or EM_PPC are ABI compliant
|
||||
*/
|
||||
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
|
||||
#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */
|
||||
#define EM_PARISC 15 /* HPPA */
|
||||
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
|
||||
#define EM_PPC 20 /* PowerPC */
|
||||
#define EM_PPC64 21 /* PowerPC 64 */
|
||||
#define EM_ARM 40 /* Advanced RISC Machines ARM */
|
||||
#define EM_ALPHA 41 /* DEC ALPHA */
|
||||
#define EM_SH 42 /* Hitachi/Renesas Super-H */
|
||||
#define EM_SPARCV9 43 /* SPARC version 9 */
|
||||
#define EM_IA_64 50 /* Intel IA-64 Processor */
|
||||
#define EM_AMD64 62 /* AMD64 architecture */
|
||||
#define EM_X86_64 EM_AMD64
|
||||
#define EM_VAX 75 /* DEC VAX */
|
||||
#define EM_AARCH64 183 /* ARM 64-bit architecture (AArch64) */
|
||||
#define EM_RISCV 243 /* RISC-V */
|
||||
|
||||
/* Non-standard */
|
||||
#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
|
||||
#define EM__LAST__ (EM_ALPHA_EXP + 1)
|
||||
|
||||
#define EM_NUM 22 /* number of machine types */
|
||||
|
||||
/* Version */
|
||||
#define EV_NONE 0 /* Invalid */
|
||||
#define EV_CURRENT 1 /* Current */
|
||||
#define EV_NUM 2 /* number of versions */
|
||||
|
||||
/* Magic for e_phnum: get real value from sh_info of first section header */
|
||||
#define PN_XNUM 0xffff
|
||||
|
||||
/* Section Header */
|
||||
typedef struct {
|
||||
Elf32_Word sh_name; /* name - index into section header
|
||||
string table section */
|
||||
Elf32_Word sh_type; /* type */
|
||||
Elf32_Word sh_flags; /* flags */
|
||||
Elf32_Addr sh_addr; /* address */
|
||||
Elf32_Off sh_offset; /* file offset */
|
||||
Elf32_Word sh_size; /* section size */
|
||||
Elf32_Word sh_link; /* section header table index link */
|
||||
Elf32_Word sh_info; /* extra information */
|
||||
Elf32_Word sh_addralign; /* address alignment */
|
||||
Elf32_Word sh_entsize; /* section entry size */
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word sh_name; /* section name */
|
||||
Elf64_Word sh_type; /* section type */
|
||||
Elf64_Xword sh_flags; /* section flags */
|
||||
Elf64_Addr sh_addr; /* virtual address */
|
||||
Elf64_Off sh_offset; /* file offset */
|
||||
Elf64_Xword sh_size; /* section size */
|
||||
Elf64_Word sh_link; /* link to another */
|
||||
Elf64_Word sh_info; /* misc info */
|
||||
Elf64_Xword sh_addralign; /* memory alignment */
|
||||
Elf64_Xword sh_entsize; /* table entry size */
|
||||
} Elf64_Shdr;
|
||||
|
||||
/* Special Section Indexes */
|
||||
#define SHN_UNDEF 0 /* undefined */
|
||||
#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
|
||||
#define SHN_LOPROC 0xff00 /* reserved range for processor */
|
||||
#define SHN_HIPROC 0xff1f /* specific section indexes */
|
||||
#define SHN_ABS 0xfff1 /* absolute value */
|
||||
#define SHN_COMMON 0xfff2 /* common symbol */
|
||||
#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
|
||||
#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
|
||||
|
||||
/* sh_type */
|
||||
#define SHT_NULL 0 /* inactive */
|
||||
#define SHT_PROGBITS 1 /* program defined information */
|
||||
#define SHT_SYMTAB 2 /* symbol table section */
|
||||
#define SHT_STRTAB 3 /* string table section */
|
||||
#define SHT_RELA 4 /* relocation section with addends*/
|
||||
#define SHT_HASH 5 /* symbol hash table section */
|
||||
#define SHT_DYNAMIC 6 /* dynamic section */
|
||||
#define SHT_NOTE 7 /* note section */
|
||||
#define SHT_NOBITS 8 /* no space section */
|
||||
#define SHT_REL 9 /* relocation section without addends */
|
||||
#define SHT_SHLIB 10 /* reserved - purpose unknown */
|
||||
#define SHT_DYNSYM 11 /* dynamic symbol table section */
|
||||
#define SHT_NUM 12 /* number of section types */
|
||||
#define SHT_INIT_ARRAY 14 /* pointers to init functions */
|
||||
#define SHT_FINI_ARRAY 15 /* pointers to termination functions */
|
||||
#define SHT_PREINIT_ARRAY 16 /* ptrs to funcs called before init */
|
||||
#define SHT_GROUP 17 /* defines a section group */
|
||||
#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
|
||||
#define SHT_RELR 19 /* relative-only relocation section */
|
||||
#define SHT_LOOS 0x60000000 /* reserved range for OS specific */
|
||||
#define SHT_SUNW_dof 0x6ffffff4 /* used by dtrace */
|
||||
#define SHT_GNU_LIBLIST 0x6ffffff7 /* libraries to be prelinked */
|
||||
#define SHT_SUNW_move 0x6ffffffa /* inf for partially init'ed symbols */
|
||||
#define SHT_SUNW_syminfo 0x6ffffffc /* ad symbol information */
|
||||
#define SHT_SUNW_verdef 0x6ffffffd /* symbol versioning inf */
|
||||
#define SHT_SUNW_verneed 0x6ffffffe /* symbol versioning req */
|
||||
#define SHT_SUNW_versym 0x6fffffff /* symbol versioning table */
|
||||
#define SHT_HIOS 0x6fffffff /* section header types */
|
||||
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
|
||||
#define SHT_HIPROC 0x7fffffff /* specific section header types */
|
||||
#define SHT_LOUSER 0x80000000 /* reserved range for application */
|
||||
#define SHT_HIUSER 0xffffffff /* specific indexes */
|
||||
|
||||
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table section */
|
||||
|
||||
/* Section names */
|
||||
#define ELF_BSS ".bss" /* uninitialized data */
|
||||
#define ELF_DATA ".data" /* initialized data */
|
||||
#define ELF_CTF ".SUNW_ctf" /* CTF data */
|
||||
#define ELF_DEBUG ".debug" /* debug */
|
||||
#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
|
||||
#define ELF_DYNSTR ".dynstr" /* dynamic string table */
|
||||
#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
|
||||
#define ELF_FINI ".fini" /* termination code */
|
||||
#define ELF_GOT ".got" /* global offset table */
|
||||
#define ELF_HASH ".hash" /* symbol hash table */
|
||||
#define ELF_INIT ".init" /* initialization code */
|
||||
#define ELF_REL_DATA ".rel.data" /* relocation data */
|
||||
#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
|
||||
#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
|
||||
#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */
|
||||
#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
|
||||
#define ELF_REL_TEXT ".rel.text" /* relocation code */
|
||||
#define ELF_RODATA ".rodata" /* read-only data */
|
||||
#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
|
||||
#define ELF_STRTAB ".strtab" /* string table */
|
||||
#define ELF_SYMTAB ".symtab" /* symbol table */
|
||||
#define ELF_TEXT ".text" /* code */
|
||||
#define ELF_OPENBSDRANDOMDATA ".openbsd.randomdata" /* constant randomdata */
|
||||
#define ELF_OPENBSDMUTABLE ".openbsd.mutable" /* mutable bss */
|
||||
|
||||
|
||||
/* Section Attribute Flags - sh_flags */
|
||||
#define SHF_WRITE 0x1 /* Writable */
|
||||
#define SHF_ALLOC 0x2 /* occupies memory */
|
||||
#define SHF_EXECINSTR 0x4 /* executable */
|
||||
#define SHF_MERGE 0x10 /* may be merged */
|
||||
#define SHF_STRINGS 0x20 /* contains strings */
|
||||
#define SHF_INFO_LINK 0x40 /* sh_info holds section index */
|
||||
#define SHF_LINK_ORDER 0x80 /* ordering requirements */
|
||||
#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required */
|
||||
#define SHF_GROUP 0x200 /* member of section group */
|
||||
#define SHF_TLS 0x400 /* thread local storage */
|
||||
#define SHF_COMPRESSED 0x800 /* contains compressed data */
|
||||
#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics */
|
||||
#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */
|
||||
/* specific section attributes */
|
||||
|
||||
/* Symbol Table Entry */
|
||||
typedef struct elf32_sym {
|
||||
Elf32_Word st_name; /* name - index into string table */
|
||||
Elf32_Addr st_value; /* symbol value */
|
||||
Elf32_Word st_size; /* symbol size */
|
||||
unsigned char st_info; /* type and binding */
|
||||
unsigned char st_other; /* 0 - no defined meaning */
|
||||
Elf32_Half st_shndx; /* section header index */
|
||||
} Elf32_Sym;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word st_name; /* Symbol name index in str table */
|
||||
unsigned char st_info; /* type / binding attrs */
|
||||
unsigned char st_other; /* unused */
|
||||
Elf64_Half st_shndx; /* section index of symbol */
|
||||
Elf64_Addr st_value; /* value of symbol */
|
||||
Elf64_Xword st_size; /* size of symbol */
|
||||
} Elf64_Sym;
|
||||
|
||||
/* Symbol table index */
|
||||
#define STN_UNDEF 0 /* undefined */
|
||||
|
||||
/* Extract symbol info - st_info */
|
||||
#define ELF32_ST_BIND(x) ((x) >> 4)
|
||||
#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
|
||||
#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf))
|
||||
|
||||
#define ELF64_ST_BIND(x) ((x) >> 4)
|
||||
#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf)
|
||||
#define ELF64_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf))
|
||||
|
||||
/* Symbol Binding - ELF32_ST_BIND - st_info */
|
||||
#define STB_LOCAL 0 /* Local symbol */
|
||||
#define STB_GLOBAL 1 /* Global symbol */
|
||||
#define STB_WEAK 2 /* like global - lower precedence */
|
||||
#define STB_NUM 3 /* number of symbol bindings */
|
||||
#define STB_LOPROC 13 /* reserved range for processor */
|
||||
#define STB_HIPROC 15 /* specific symbol bindings */
|
||||
|
||||
/* Symbol type - ELF32_ST_TYPE - st_info */
|
||||
#define STT_NOTYPE 0 /* not specified */
|
||||
#define STT_OBJECT 1 /* data object */
|
||||
#define STT_FUNC 2 /* function */
|
||||
#define STT_SECTION 3 /* section */
|
||||
#define STT_FILE 4 /* file */
|
||||
#define STT_TLS 6 /* thread local storage */
|
||||
#define STT_LOPROC 13 /* reserved range for processor */
|
||||
#define STT_HIPROC 15 /* specific symbol types */
|
||||
|
||||
/* Extract symbol visibility - st_other */
|
||||
#define ELF_ST_VISIBILITY(v) ((v) & 0x3)
|
||||
#define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY
|
||||
#define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY
|
||||
|
||||
#define STV_DEFAULT 0 /* Visibility set by binding type */
|
||||
#define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */
|
||||
#define STV_HIDDEN 2 /* can only be seen inside own .so */
|
||||
#define STV_PROTECTED 3 /* HIDDEN inside, DEFAULT outside */
|
||||
|
||||
/* Relocation entry with implicit addend */
|
||||
typedef struct {
|
||||
Elf32_Addr r_offset; /* offset of relocation */
|
||||
Elf32_Word r_info; /* symbol table index and type */
|
||||
} Elf32_Rel;
|
||||
|
||||
/* Relocation entry with explicit addend */
|
||||
typedef struct {
|
||||
Elf32_Addr r_offset; /* offset of relocation */
|
||||
Elf32_Word r_info; /* symbol table index and type */
|
||||
Elf32_Sword r_addend;
|
||||
} Elf32_Rela;
|
||||
|
||||
/* Extract relocation info - r_info */
|
||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||
#define ELF32_R_TYPE(i) ((unsigned char) (i))
|
||||
#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t))
|
||||
|
||||
typedef struct {
|
||||
Elf64_Addr r_offset; /* where to do it */
|
||||
Elf64_Xword r_info; /* index & type of relocation */
|
||||
} Elf64_Rel;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Addr r_offset; /* where to do it */
|
||||
Elf64_Xword r_info; /* index & type of relocation */
|
||||
Elf64_Sxword r_addend; /* adjustment value */
|
||||
} Elf64_Rela;
|
||||
|
||||
#define ELF64_R_SYM(info) ((info) >> 32)
|
||||
#define ELF64_R_TYPE(info) ((info) & 0xFFFFFFFF)
|
||||
#define ELF64_R_INFO(s,t) (((s) << 32) + (__uint32_t)(t))
|
||||
|
||||
#if defined(__mips64__) && defined(__MIPSEL__)
|
||||
/*
|
||||
* The 64-bit MIPS ELF ABI uses a slightly different relocation format
|
||||
* than the regular ELF ABI: the r_info field is split into several
|
||||
* pieces (see gnu/usr.bin/binutils-2.17/include/elf/mips.h for details).
|
||||
*/
|
||||
#undef ELF64_R_SYM
|
||||
#undef ELF64_R_TYPE
|
||||
#undef ELF64_R_INFO
|
||||
#define ELF64_R_TYPE(info) ((__uint64_t)swap32((info) >> 32))
|
||||
#define ELF64_R_SYM(info) ((info) & 0xFFFFFFFF)
|
||||
#define ELF64_R_INFO(s,t) (((__uint64_t)swap32(t) << 32) + (__uint32_t)(s))
|
||||
#endif /* __mips64__ && __MIPSEL__ */
|
||||
|
||||
/*
|
||||
* Relative Relocation info.
|
||||
* c.f. decode_relrs() in gnu/llvm/llvm/lib/Object/ELF.cpp
|
||||
*/
|
||||
typedef Elf32_Word Elf32_Relr;
|
||||
typedef Elf64_Xword Elf64_Relr;
|
||||
|
||||
/* Program Header */
|
||||
typedef struct {
|
||||
Elf32_Word p_type; /* segment type */
|
||||
Elf32_Off p_offset; /* segment offset */
|
||||
Elf32_Addr p_vaddr; /* virtual address of segment */
|
||||
Elf32_Addr p_paddr; /* physical address - ignored? */
|
||||
Elf32_Word p_filesz; /* number of bytes in file for seg. */
|
||||
Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
|
||||
Elf32_Word p_flags; /* flags */
|
||||
Elf32_Word p_align; /* memory alignment */
|
||||
} Elf32_Phdr;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word p_type; /* entry type */
|
||||
Elf64_Word p_flags; /* flags */
|
||||
Elf64_Off p_offset; /* offset */
|
||||
Elf64_Addr p_vaddr; /* virtual address */
|
||||
Elf64_Addr p_paddr; /* physical address */
|
||||
Elf64_Xword p_filesz; /* file size */
|
||||
Elf64_Xword p_memsz; /* memory size */
|
||||
Elf64_Xword p_align; /* memory & file alignment */
|
||||
} Elf64_Phdr;
|
||||
|
||||
/* Segment types - p_type */
|
||||
#define PT_NULL 0 /* unused */
|
||||
#define PT_LOAD 1 /* loadable segment */
|
||||
#define PT_DYNAMIC 2 /* dynamic linking section */
|
||||
#define PT_INTERP 3 /* the RTLD */
|
||||
#define PT_NOTE 4 /* auxiliary information */
|
||||
#define PT_SHLIB 5 /* reserved - purpose undefined */
|
||||
#define PT_PHDR 6 /* program header */
|
||||
#define PT_TLS 7 /* thread local storage */
|
||||
#define PT_LOOS 0x60000000 /* reserved range for OS */
|
||||
#define PT_HIOS 0x6fffffff /* specific segment types */
|
||||
#define PT_LOPROC 0x70000000 /* reserved range for processor */
|
||||
#define PT_HIPROC 0x7fffffff /* specific segment types */
|
||||
|
||||
#define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling info */
|
||||
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||
|
||||
#define PT_OPENBSD_MUTABLE 0x65a3dbe5 /* like bss, but not immutable */
|
||||
#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */
|
||||
#define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X violations */
|
||||
#define PT_OPENBSD_BOOTDATA 0x65a41be6 /* section for boot arguments */
|
||||
|
||||
/* Segment flags - p_flags */
|
||||
#define PF_X 0x1 /* Executable */
|
||||
#define PF_W 0x2 /* Writable */
|
||||
#define PF_R 0x4 /* Readable */
|
||||
#define PF_MASKOS 0x0ff00000 /* reserved bits for OS */
|
||||
/* specific segment flags */
|
||||
#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
|
||||
/* specific segment flags */
|
||||
|
||||
#define PF_OPENBSD_MUTABLE 0x08000000 /* Mutable */
|
||||
|
||||
/* Dynamic structure */
|
||||
typedef struct {
|
||||
Elf32_Sword d_tag; /* controls meaning of d_val */
|
||||
union {
|
||||
Elf32_Word d_val; /* Multiple meanings - see d_tag */
|
||||
Elf32_Addr d_ptr; /* program virtual address */
|
||||
} d_un;
|
||||
} Elf32_Dyn;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Xword d_tag; /* controls meaning of d_val */
|
||||
union {
|
||||
Elf64_Addr d_ptr;
|
||||
Elf64_Xword d_val;
|
||||
} d_un;
|
||||
} Elf64_Dyn;
|
||||
|
||||
/* Dynamic Array Tags - d_tag */
|
||||
#define DT_NULL 0 /* marks end of _DYNAMIC array */
|
||||
#define DT_NEEDED 1 /* string table offset of needed lib */
|
||||
#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
|
||||
#define DT_PLTGOT 3 /* address PLT/GOT */
|
||||
#define DT_HASH 4 /* address of symbol hash table */
|
||||
#define DT_STRTAB 5 /* address of string table */
|
||||
#define DT_SYMTAB 6 /* address of symbol table */
|
||||
#define DT_RELA 7 /* address of relocation table */
|
||||
#define DT_RELASZ 8 /* size of relocation table */
|
||||
#define DT_RELAENT 9 /* size of relocation entry */
|
||||
#define DT_STRSZ 10 /* size of string table */
|
||||
#define DT_SYMENT 11 /* size of symbol table entry */
|
||||
#define DT_INIT 12 /* address of initialization func. */
|
||||
#define DT_FINI 13 /* address of termination function */
|
||||
#define DT_SONAME 14 /* string table offset of shared obj */
|
||||
#define DT_RPATH 15 /* string table offset of library
|
||||
search path */
|
||||
#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
|
||||
#define DT_REL 17 /* address of rel. tbl. w addends */
|
||||
#define DT_RELSZ 18 /* size of DT_REL relocation table */
|
||||
#define DT_RELENT 19 /* size of DT_REL relocation entry */
|
||||
#define DT_PLTREL 20 /* PLT referenced relocation entry */
|
||||
#define DT_DEBUG 21 /* bugger */
|
||||
#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
|
||||
#define DT_JMPREL 23 /* add. of PLT's relocation entries */
|
||||
#define DT_BIND_NOW 24 /* Bind now regardless of env setting */
|
||||
#define DT_INIT_ARRAY 25 /* address of array of init func */
|
||||
#define DT_FINI_ARRAY 26 /* address of array of term func */
|
||||
#define DT_INIT_ARRAYSZ 27 /* size of array of init func */
|
||||
#define DT_FINI_ARRAYSZ 28 /* size of array of term func */
|
||||
#define DT_RUNPATH 29 /* strtab offset of lib search path */
|
||||
#define DT_FLAGS 30 /* Set of DF_* flags */
|
||||
#define DT_ENCODING 31 /* further DT_* follow encoding rules */
|
||||
#define DT_PREINIT_ARRAY 32 /* address of array of preinit func */
|
||||
#define DT_PREINIT_ARRAYSZ 33 /* size of array of preinit func */
|
||||
#define DT_RELRSZ 35 /* size of DT_RELR relocation table */
|
||||
#define DT_RELR 36 /* addr of DT_RELR relocation table */
|
||||
#define DT_RELRENT 37 /* size of DT_RELR relocation entry */
|
||||
#define DT_LOOS 0x6000000d /* reserved range for OS */
|
||||
#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */
|
||||
#define DT_LOPROC 0x70000000 /* reserved range for processor */
|
||||
#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
|
||||
|
||||
/* some other useful tags */
|
||||
#define DT_GNU_HASH 0x6ffffef5 /* address of GNU hash table */
|
||||
#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */
|
||||
#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */
|
||||
#define DT_FLAGS_1 0x6ffffffb
|
||||
|
||||
/* Dynamic Flags - DT_FLAGS .dynamic entry */
|
||||
#define DF_ORIGIN 0x00000001
|
||||
#define DF_SYMBOLIC 0x00000002
|
||||
#define DF_TEXTREL 0x00000004
|
||||
#define DF_BIND_NOW 0x00000008
|
||||
#define DF_STATIC_TLS 0x00000010
|
||||
|
||||
/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */
|
||||
#define DF_1_NOW 0x00000001
|
||||
#define DF_1_GLOBAL 0x00000002
|
||||
#define DF_1_GROUP 0x00000004
|
||||
#define DF_1_NODELETE 0x00000008
|
||||
#define DF_1_LOADFLTR 0x00000010
|
||||
#define DF_1_INITFIRST 0x00000020
|
||||
#define DF_1_NOOPEN 0x00000040
|
||||
#define DF_1_ORIGIN 0x00000080
|
||||
#define DF_1_DIRECT 0x00000100
|
||||
#define DF_1_TRANS 0x00000200
|
||||
#define DF_1_INTERPOSE 0x00000400
|
||||
#define DF_1_NODEFLIB 0x00000800
|
||||
#define DF_1_NODUMP 0x00001000
|
||||
#define DF_1_CONLFAT 0x00002000
|
||||
#define DF_1_ENDFILTEE 0x00004000
|
||||
#define DF_1_DISPRELDNE 0x00008000
|
||||
#define DF_1_DISPRELPND 0x00010000
|
||||
#define DF_1_NODIRECT 0x00020000
|
||||
#define DF_1_IGNMULDEF 0x00040000
|
||||
#define DF_1_NOKSYMS 0x00080000
|
||||
#define DF_1_NOHDR 0x00100000
|
||||
#define DF_1_EDITED 0x00200000
|
||||
#define DF_1_NORELOC 0x00400000
|
||||
#define DF_1_SYMINTPOSE 0x00800000
|
||||
#define DF_1_GLOBAUDIT 0x01000000
|
||||
#define DF_1_SINGLETON 0x02000000
|
||||
#define DF_1_PIE 0x08000000
|
||||
|
||||
/*
|
||||
* Note header
|
||||
*/
|
||||
typedef struct {
|
||||
Elf32_Word n_namesz;
|
||||
Elf32_Word n_descsz;
|
||||
Elf32_Word n_type;
|
||||
} Elf32_Nhdr;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word n_namesz;
|
||||
Elf64_Word n_descsz;
|
||||
Elf64_Word n_type;
|
||||
} Elf64_Nhdr;
|
||||
|
||||
/*
|
||||
* Note Definitions
|
||||
*/
|
||||
typedef struct {
|
||||
Elf32_Word namesz;
|
||||
Elf32_Word descsz;
|
||||
Elf32_Word type;
|
||||
} Elf32_Note;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word namesz;
|
||||
Elf64_Word descsz;
|
||||
Elf64_Word type;
|
||||
} Elf64_Note;
|
||||
|
||||
/* Values for n_type. */
|
||||
#define NT_PRSTATUS 1 /* Process status. */
|
||||
#define NT_FPREGSET 2 /* Floating point registers. */
|
||||
#define NT_PRPSINFO 3 /* Process state info. */
|
||||
|
||||
/*
|
||||
* OpenBSD-specific core file information.
|
||||
*
|
||||
* OpenBSD ELF core files use notes to provide information about
|
||||
* the process's state. The note name is "OpenBSD" for information
|
||||
* that is global to the process, and "OpenBSD@nn", where "nn" is the
|
||||
* thread ID of the thread that the information belongs to (such as
|
||||
* register state).
|
||||
*
|
||||
* We use the following note identifiers:
|
||||
*
|
||||
* NT_OPENBSD_PROCINFO
|
||||
* Note is a "elfcore_procinfo" structure.
|
||||
* NT_OPENBSD_AUXV
|
||||
* Note is a a bunch of Auxiliary Vectors, terminated by
|
||||
* an AT_NULL entry.
|
||||
* NT_OPENBSD_REGS
|
||||
* Note is a "reg" structure.
|
||||
* NT_OPENBSD_FPREGS
|
||||
* Note is a "fpreg" structure.
|
||||
*
|
||||
* Please try to keep the members of the "elfcore_procinfo" structure
|
||||
* nicely aligned, and if you add elements, add them to the end and
|
||||
* bump the version.
|
||||
*/
|
||||
|
||||
#define NT_OPENBSD_PROCINFO 10
|
||||
#define NT_OPENBSD_AUXV 11
|
||||
|
||||
#define NT_OPENBSD_REGS 20
|
||||
#define NT_OPENBSD_FPREGS 21
|
||||
#define NT_OPENBSD_XFPREGS 22
|
||||
#define NT_OPENBSD_WCOOKIE 23
|
||||
|
||||
struct elfcore_procinfo {
|
||||
/* Version 1 fields start here. */
|
||||
uint32_t cpi_version; /* netbsd_elfcore_procinfo version */
|
||||
#define ELFCORE_PROCINFO_VERSION 1
|
||||
uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */
|
||||
uint32_t cpi_signo; /* killing signal */
|
||||
uint32_t cpi_sigcode; /* signal code */
|
||||
uint32_t cpi_sigpend; /* pending signals */
|
||||
uint32_t cpi_sigmask; /* blocked signals */
|
||||
uint32_t cpi_sigignore; /* ignored signals */
|
||||
uint32_t cpi_sigcatch; /* signals being caught by user */
|
||||
int32_t cpi_pid; /* process ID */
|
||||
int32_t cpi_ppid; /* parent process ID */
|
||||
int32_t cpi_pgrp; /* process group ID */
|
||||
int32_t cpi_sid; /* session ID */
|
||||
uint32_t cpi_ruid; /* real user ID */
|
||||
uint32_t cpi_euid; /* effective user ID */
|
||||
uint32_t cpi_svuid; /* saved user ID */
|
||||
uint32_t cpi_rgid; /* real group ID */
|
||||
uint32_t cpi_egid; /* effective group ID */
|
||||
uint32_t cpi_svgid; /* saved group ID */
|
||||
int8_t cpi_name[32]; /* copy of pr->ps_comm */
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX - these _KERNEL items aren't part of the ABI!
|
||||
*/
|
||||
#if defined(_KERNEL) || defined(_DYN_LOADER)
|
||||
|
||||
#define ELF32_NO_ADDR ((uint32_t) ~0) /* Indicates addr. not yet filled in */
|
||||
|
||||
typedef struct {
|
||||
Elf32_Sword au_id; /* 32-bit id */
|
||||
Elf32_Word au_v; /* 32-bit value */
|
||||
} Aux32Info;
|
||||
|
||||
#define ELF64_NO_ADDR ((__uint64_t) ~0)/* Indicates addr. not yet filled in */
|
||||
|
||||
typedef struct {
|
||||
Elf64_Shalf au_id; /* 32-bit id */
|
||||
Elf64_Xword au_v; /* 64-bit value */
|
||||
} Aux64Info;
|
||||
|
||||
enum AuxID {
|
||||
AUX_null = 0,
|
||||
AUX_ignore = 1,
|
||||
AUX_execfd = 2,
|
||||
AUX_phdr = 3, /* &phdr[0] */
|
||||
AUX_phent = 4, /* sizeof(phdr[0]) */
|
||||
AUX_phnum = 5, /* # phdr entries */
|
||||
AUX_pagesz = 6, /* PAGESIZE */
|
||||
AUX_base = 7, /* base addr for ld.so or static PIE */
|
||||
AUX_flags = 8, /* processor flags */
|
||||
AUX_entry = 9, /* a.out entry */
|
||||
AUX_sun_uid = 2000, /* euid */
|
||||
AUX_sun_ruid = 2001, /* ruid */
|
||||
AUX_sun_gid = 2002, /* egid */
|
||||
AUX_sun_rgid = 2003, /* rgid */
|
||||
AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
|
||||
};
|
||||
|
||||
struct elf_args {
|
||||
u_long arg_entry; /* program entry point */
|
||||
u_long arg_interp; /* Interpreter load address */
|
||||
u_long arg_phaddr; /* program header address */
|
||||
u_long arg_phentsize; /* Size of program header */
|
||||
u_long arg_phnum; /* Number of program headers */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE)
|
||||
#define ELFSIZE ARCH_ELFSIZE
|
||||
#endif
|
||||
|
||||
#if defined(ELFSIZE)
|
||||
#define CONCAT(x,y) __CONCAT(x,y)
|
||||
#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
|
||||
#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
|
||||
#endif
|
||||
|
||||
#if defined(ELFSIZE) && (ELFSIZE == 32)
|
||||
#define Elf_Ehdr Elf32_Ehdr
|
||||
#define Elf_Phdr Elf32_Phdr
|
||||
#define Elf_Shdr Elf32_Shdr
|
||||
#define Elf_Sym Elf32_Sym
|
||||
#define Elf_Rel Elf32_Rel
|
||||
#define Elf_RelA Elf32_Rela
|
||||
#define Elf_Relr Elf32_Relr
|
||||
#define Elf_Dyn Elf32_Dyn
|
||||
#define Elf_Half Elf32_Half
|
||||
#define Elf_Word Elf32_Word
|
||||
#define Elf_Sword Elf32_Sword
|
||||
#define Elf_Addr Elf32_Addr
|
||||
#define Elf_Off Elf32_Off
|
||||
#define Elf_Nhdr Elf32_Nhdr
|
||||
#define Elf_Note Elf32_Note
|
||||
|
||||
#define ELF_R_SYM ELF32_R_SYM
|
||||
#define ELF_R_TYPE ELF32_R_TYPE
|
||||
#define ELF_R_INFO ELF32_R_INFO
|
||||
#define ELFCLASS ELFCLASS32
|
||||
|
||||
#define ELF_ST_BIND ELF32_ST_BIND
|
||||
#define ELF_ST_TYPE ELF32_ST_TYPE
|
||||
#define ELF_ST_INFO ELF32_ST_INFO
|
||||
|
||||
#define ELF_NO_ADDR ELF32_NO_ADDR
|
||||
#define AuxInfo Aux32Info
|
||||
#elif defined(ELFSIZE) && (ELFSIZE == 64)
|
||||
#define Elf_Ehdr Elf64_Ehdr
|
||||
#define Elf_Phdr Elf64_Phdr
|
||||
#define Elf_Shdr Elf64_Shdr
|
||||
#define Elf_Sym Elf64_Sym
|
||||
#define Elf_Rel Elf64_Rel
|
||||
#define Elf_RelA Elf64_Rela
|
||||
#define Elf_Relr Elf64_Relr
|
||||
#define Elf_Dyn Elf64_Dyn
|
||||
#define Elf_Half Elf64_Half
|
||||
#define Elf_Word Elf64_Word
|
||||
#define Elf_Sword Elf64_Sword
|
||||
#define Elf_Addr Elf64_Addr
|
||||
#define Elf_Off Elf64_Off
|
||||
#define Elf_Nhdr Elf64_Nhdr
|
||||
#define Elf_Note Elf64_Note
|
||||
|
||||
#define ELF_R_SYM ELF64_R_SYM
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#define ELF_R_INFO ELF64_R_INFO
|
||||
#define ELFCLASS ELFCLASS64
|
||||
|
||||
#define ELF_ST_BIND ELF64_ST_BIND
|
||||
#define ELF_ST_TYPE ELF64_ST_TYPE
|
||||
#define ELF_ST_INFO ELF64_ST_INFO
|
||||
|
||||
#define ELF_NO_ADDR ELF64_NO_ADDR
|
||||
#define AuxInfo Aux64Info
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* How many entries are in the AuxInfo array we pass to the process?
|
||||
*/
|
||||
#define ELF_AUX_ENTRIES 9
|
||||
#define ELF_AUX_WORDS (sizeof(AuxInfo) * ELF_AUX_ENTRIES / sizeof(char *))
|
||||
|
||||
struct exec_package;
|
||||
|
||||
int exec_elf_makecmds(struct proc *, struct exec_package *);
|
||||
int exec_elf_fixup(struct proc *, struct exec_package *);
|
||||
int coredump_elf(struct proc *, void *);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#define ELF_TARG_VER 1 /* The ver for which this code is intended */
|
||||
|
||||
#endif /* _SYS_EXEC_ELF_H_ */
|
||||
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <elf/elf.h>
|
||||
#include <elf/elf32.h>
|
||||
#include <elf/elf64.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* ELF header functions */
|
||||
int elf_newFile(const void *file, size_t size, elf_t *res)
|
||||
{
|
||||
return elf_newFile_maybe_unsafe(file, size, true, true, res);
|
||||
}
|
||||
|
||||
int elf_newFile_maybe_unsafe(const void *file, size_t size, bool check_pht, bool check_st, elf_t *res)
|
||||
{
|
||||
elf_t new_file = {
|
||||
.elfFile = file,
|
||||
.elfSize = size
|
||||
};
|
||||
|
||||
int status = elf_checkFile(&new_file);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (check_pht) {
|
||||
status = elf_checkProgramHeaderTable(&new_file);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (check_st) {
|
||||
status = elf_checkSectionTable(&new_file);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (res) {
|
||||
*res = new_file;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int elf_check_magic(const char *file)
|
||||
{
|
||||
if (memcmp(file, ELFMAG, SELFMAG) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks that elfFile points to a valid elf file. Returns 0 if the elf
|
||||
* file is valid, < 0 if invalid.
|
||||
*/
|
||||
int elf_checkFile(elf_t *elfFile)
|
||||
{
|
||||
int res = elf32_checkFile(elfFile);
|
||||
if (res == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = elf64_checkFile(elfFile);
|
||||
if (res == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int elf_checkProgramHeaderTable(const elf_t *elfFile)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_checkProgramHeaderTable(elfFile);
|
||||
} else {
|
||||
return elf64_checkProgramHeaderTable(elfFile);
|
||||
}
|
||||
}
|
||||
|
||||
int elf_checkSectionTable(const elf_t *elfFile)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_checkSectionTable(elfFile);
|
||||
} else {
|
||||
return elf64_checkSectionTable(elfFile);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t elf_getEntryPoint(const elf_t *elfFile)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getEntryPoint(elfFile);
|
||||
} else {
|
||||
return elf64_getEntryPoint(elfFile);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getNumProgramHeaders(const elf_t *elfFile)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getNumProgramHeaders(elfFile);
|
||||
} else {
|
||||
return elf64_getNumProgramHeaders(elfFile);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getNumSections(const elf_t *elfFile)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getNumSections(elfFile);
|
||||
} else {
|
||||
return elf64_getNumSections(elfFile);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getSectionStringTableIndex(const elf_t *elf)
|
||||
{
|
||||
if (elf_isElf32(elf)) {
|
||||
return elf32_getSectionStringTableIndex(elf);
|
||||
} else {
|
||||
return elf64_getSectionStringTableIndex(elf);
|
||||
}
|
||||
}
|
||||
|
||||
const char *elf_getStringTable(const elf_t *elf, size_t string_segment)
|
||||
{
|
||||
const char *string_table = elf_getSection(elf, string_segment);
|
||||
if (string_table == NULL) {
|
||||
return NULL; /* no such section */
|
||||
}
|
||||
|
||||
if (elf_getSectionType(elf, string_segment) != SHT_STRTAB) {
|
||||
return NULL; /* not a string table */
|
||||
}
|
||||
|
||||
size_t size = elf_getSectionSize(elf, string_segment);
|
||||
if (string_table[size - 1] != 0) {
|
||||
return NULL; /* string table is not null-terminated */
|
||||
}
|
||||
|
||||
return string_table;
|
||||
}
|
||||
|
||||
const char *elf_getSectionStringTable(const elf_t *elf)
|
||||
{
|
||||
size_t index = elf_getSectionStringTableIndex(elf);
|
||||
return elf_getStringTable(elf, index);
|
||||
}
|
||||
|
||||
|
||||
/* Section header functions */
|
||||
const void *elf_getSection(const elf_t *elf, size_t i)
|
||||
{
|
||||
if (i == 0 || i >= elf_getNumSections(elf)) {
|
||||
return NULL; /* no such section */
|
||||
}
|
||||
|
||||
size_t section_offset = elf_getSectionOffset(elf, i);
|
||||
size_t section_size = elf_getSectionSize(elf, i);
|
||||
if (section_size == 0) {
|
||||
return NULL; /* section is empty */
|
||||
}
|
||||
|
||||
size_t section_end = section_offset + section_size;
|
||||
/* possible wraparound - check that section end is not before section start */
|
||||
if (section_end > elf->elfSize || section_end < section_offset) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (char *)elf->elfFile + section_offset;
|
||||
}
|
||||
|
||||
const void *elf_getSectionNamed(const elf_t *elfFile, const char *str, size_t *id)
|
||||
{
|
||||
size_t numSections = elf_getNumSections(elfFile);
|
||||
for (size_t i = 0; i < numSections; i++) {
|
||||
if (strcmp(str, elf_getSectionName(elfFile, i)) == 0) {
|
||||
if (id != NULL) {
|
||||
*id = i;
|
||||
}
|
||||
return elf_getSection(elfFile, i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *elf_getSectionName(const elf_t *elf, size_t i)
|
||||
{
|
||||
size_t str_table_idx = elf_getSectionStringTableIndex(elf);
|
||||
const char *str_table = elf_getStringTable(elf, str_table_idx);
|
||||
size_t offset = elf_getSectionNameOffset(elf, i);
|
||||
size_t size = elf_getSectionSize(elf, str_table_idx);
|
||||
|
||||
if (str_table == NULL || offset > size) {
|
||||
return "<corrupted>";
|
||||
}
|
||||
|
||||
return str_table + offset;
|
||||
}
|
||||
|
||||
size_t elf_getSectionNameOffset(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionNameOffset(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionNameOffset(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t elf_getSectionType(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionType(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionType(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getSectionFlags(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionFlags(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionFlags(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t elf_getSectionAddr(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionAddr(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionAddr(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getSectionOffset(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionOffset(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionOffset(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getSectionSize(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionSize(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionSize(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t elf_getSectionLink(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionLink(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionLink(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t elf_getSectionInfo(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionInfo(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionInfo(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getSectionAddrAlign(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionAddrAlign(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionAddrAlign(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getSectionEntrySize(const elf_t *elfFile, size_t i)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getSectionEntrySize(elfFile, i);
|
||||
} else {
|
||||
return elf64_getSectionEntrySize(elfFile, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Program headers function */
|
||||
const void *elf_getProgramSegment(const elf_t *elf, size_t ph)
|
||||
{
|
||||
size_t offset = elf_getProgramHeaderOffset(elf, ph);
|
||||
size_t file_size = elf_getProgramHeaderFileSize(elf, ph);
|
||||
size_t segment_end = offset + file_size;
|
||||
/* possible wraparound - check that segment end is not before segment start */
|
||||
if (elf->elfSize < segment_end || segment_end < offset) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (char *)elf->elfFile + offset;
|
||||
}
|
||||
|
||||
uint32_t elf_getProgramHeaderType(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderType(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderType(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getProgramHeaderOffset(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderOffset(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderOffset(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t elf_getProgramHeaderVaddr(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderVaddr(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderVaddr(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t elf_getProgramHeaderPaddr(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderPaddr(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderPaddr(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getProgramHeaderFileSize(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderFileSize(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderFileSize(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getProgramHeaderMemorySize(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderMemorySize(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderMemorySize(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t elf_getProgramHeaderFlags(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderFlags(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderFlags(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
size_t elf_getProgramHeaderAlign(const elf_t *elfFile, size_t ph)
|
||||
{
|
||||
if (elf_isElf32(elfFile)) {
|
||||
return elf32_getProgramHeaderAlign(elfFile, ph);
|
||||
} else {
|
||||
return elf64_getProgramHeaderAlign(elfFile, ph);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Utility functions */
|
||||
int elf_getMemoryBounds(const elf_t *elfFile, elf_addr_type_t addr_type, uintptr_t *min, uintptr_t *max)
|
||||
{
|
||||
uintptr_t mem_min = UINTPTR_MAX;
|
||||
uintptr_t mem_max = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) {
|
||||
uintptr_t sect_min, sect_max;
|
||||
|
||||
if (elf_getProgramHeaderMemorySize(elfFile, i) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (addr_type == PHYSICAL) {
|
||||
sect_min = elf_getProgramHeaderPaddr(elfFile, i);
|
||||
} else {
|
||||
sect_min = elf_getProgramHeaderVaddr(elfFile, i);
|
||||
}
|
||||
|
||||
sect_max = sect_min + elf_getProgramHeaderMemorySize(elfFile, i);
|
||||
|
||||
if (sect_max > mem_max) {
|
||||
mem_max = sect_max;
|
||||
}
|
||||
if (sect_min < mem_min) {
|
||||
mem_min = sect_min;
|
||||
}
|
||||
}
|
||||
*min = mem_min;
|
||||
*max = mem_max;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int elf_vaddrInProgramHeader(const elf_t *elfFile, size_t ph, uintptr_t vaddr)
|
||||
{
|
||||
uintptr_t min = elf_getProgramHeaderVaddr(elfFile, ph);
|
||||
uintptr_t max = min + elf_getProgramHeaderMemorySize(elfFile, ph);
|
||||
if (vaddr >= min && vaddr < max) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t elf_vtopProgramHeader(const elf_t *elfFile, size_t ph, uintptr_t vaddr)
|
||||
{
|
||||
uintptr_t ph_phys = elf_getProgramHeaderPaddr(elfFile, ph);
|
||||
uintptr_t ph_virt = elf_getProgramHeaderVaddr(elfFile, ph);
|
||||
uintptr_t paddr;
|
||||
|
||||
paddr = vaddr - ph_virt + ph_phys;
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
int elf_loadFile(const elf_t *elf, elf_addr_type_t addr_type)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < elf_getNumProgramHeaders(elf); i++) {
|
||||
/* Load that section */
|
||||
uintptr_t dest, src;
|
||||
size_t len;
|
||||
if (addr_type == PHYSICAL) {
|
||||
dest = elf_getProgramHeaderPaddr(elf, i);
|
||||
} else {
|
||||
dest = elf_getProgramHeaderVaddr(elf, i);
|
||||
}
|
||||
len = elf_getProgramHeaderFileSize(elf, i);
|
||||
src = (uintptr_t) elf->elfFile + elf_getProgramHeaderOffset(elf, i);
|
||||
memcpy((void *) dest, (void *) src, len);
|
||||
dest += len;
|
||||
memset((void *) dest, 0, elf_getProgramHeaderMemorySize(elf, i) - len);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <elf/elf.h>
|
||||
#include <elf/elf32.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ELF header functions */
|
||||
int elf32_checkFile(elf_t *elf)
|
||||
{
|
||||
if (elf->elfSize < sizeof(Elf32_Ehdr)) {
|
||||
return -1; /* file smaller than ELF header */
|
||||
}
|
||||
|
||||
if (elf_check_magic(elf->elfFile) < 0) {
|
||||
return -1; /* not an ELF file */
|
||||
}
|
||||
|
||||
Elf32_Ehdr const *header = elf->elfFile;
|
||||
if (header->e_ident[EI_CLASS] != ELFCLASS32) {
|
||||
return -1; /* not a 32-bit ELF */
|
||||
}
|
||||
|
||||
if (header->e_phentsize != sizeof(Elf32_Phdr)) {
|
||||
return -1; /* unexpected program header size */
|
||||
}
|
||||
|
||||
if (header->e_shentsize != sizeof(Elf32_Shdr)) {
|
||||
return -1; /* unexpected section header size */
|
||||
}
|
||||
|
||||
if (header->e_shstrndx >= header->e_shnum) {
|
||||
return -1; /* invalid section header string table section */
|
||||
}
|
||||
|
||||
elf->elfClass = header->e_ident[EI_CLASS];
|
||||
return 0; /* elf header looks OK */
|
||||
}
|
||||
|
||||
int elf32_checkProgramHeaderTable(const elf_t *elf)
|
||||
{
|
||||
const Elf32_Ehdr *header = elf->elfFile;
|
||||
size_t ph_end = header->e_phoff + header->e_phentsize * header->e_phnum;
|
||||
if (elf->elfSize < ph_end || ph_end < header->e_phoff) {
|
||||
return -1; /* invalid program header table */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf32_checkSectionTable(const elf_t *elf)
|
||||
{
|
||||
const Elf32_Ehdr *header = elf->elfFile;
|
||||
size_t sh_end = header->e_shoff + header->e_shentsize * header->e_shnum;
|
||||
if (elf->elfSize < sh_end || sh_end < header->e_shoff) {
|
||||
return -1; /* invalid section header table */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 University of New South Wales
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <elf/elf.h>
|
||||
#include <elf/elf64.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ELF header functions */
|
||||
int elf64_checkFile(elf_t *elf)
|
||||
{
|
||||
if (sizeof(uintptr_t) != sizeof(uint64_t)) {
|
||||
return -1; /* not supported on 32-bit architecture */
|
||||
}
|
||||
|
||||
if (elf->elfSize < sizeof(Elf64_Ehdr)) {
|
||||
return -1; /* file smaller than ELF header */
|
||||
}
|
||||
|
||||
if (elf_check_magic(elf->elfFile) < 0) {
|
||||
return -1; /* not an ELF file */
|
||||
}
|
||||
|
||||
Elf64_Ehdr const *header = elf->elfFile;
|
||||
if (header->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
return -1; /* not a 64-bit ELF */
|
||||
}
|
||||
|
||||
if (header->e_phentsize != sizeof(Elf64_Phdr)) {
|
||||
return -1; /* unexpected program header size */
|
||||
}
|
||||
|
||||
if (header->e_shentsize != sizeof(Elf64_Shdr)) {
|
||||
return -1; /* unexpected section header size */
|
||||
}
|
||||
|
||||
if (header->e_shstrndx >= header->e_shnum) {
|
||||
return -1; /* invalid section header string table section */
|
||||
}
|
||||
|
||||
elf->elfClass = header->e_ident[EI_CLASS];
|
||||
return 0; /* elf header looks OK */
|
||||
}
|
||||
|
||||
int elf64_checkProgramHeaderTable(const elf_t *elf)
|
||||
{
|
||||
const Elf64_Ehdr *header = elf->elfFile;
|
||||
size_t ph_end = header->e_phoff + header->e_phentsize * header->e_phnum;
|
||||
if (elf->elfSize < ph_end || ph_end < header->e_phoff) {
|
||||
return -1; /* invalid program header table */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf64_checkSectionTable(const elf_t *elf)
|
||||
{
|
||||
const Elf64_Ehdr *header = elf->elfFile;
|
||||
size_t sh_end = header->e_shoff + header->e_shentsize * header->e_shnum;
|
||||
if (elf->elfSize < sh_end || sh_end < header->e_shoff) {
|
||||
return -1; /* invalid section header table */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1767,6 +1767,39 @@ enum retro_mod
|
||||
* (see enum retro_savestate_context)
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT (73 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* struct retro_hw_render_context_negotiation_interface * --
|
||||
* Before calling SET_HW_RNEDER_CONTEXT_NEGOTIATION_INTERFACE, a core can query
|
||||
* which version of the interface is supported.
|
||||
*
|
||||
* Frontend looks at interface_type and returns the maximum supported
|
||||
* context negotiation interface version.
|
||||
* If the interface_type is not supported or recognized by the frontend, a version of 0
|
||||
* must be returned in interface_version and true is returned by frontend.
|
||||
*
|
||||
* If this environment call returns true with interface_version greater than 0,
|
||||
* a core can always use a negotiation interface version larger than what the frontend returns, but only
|
||||
* earlier versions of the interface will be used by the frontend.
|
||||
* A frontend must not reject a negotiation interface version that is larger than
|
||||
* what the frontend supports. Instead, the frontend will use the older entry points that it recognizes.
|
||||
* If this is incompatible with a particular core's requirements, it can error out early.
|
||||
*
|
||||
* Backwards compatibility note:
|
||||
* This environment call was introduced after Vulkan v1 context negotiation.
|
||||
* If this environment call is not supported by frontend - i.e. the environment call returns false -
|
||||
* only Vulkan v1 context negotiation is supported (if Vulkan HW rendering is supported at all).
|
||||
* If a core uses Vulkan negotiation interface with version > 1, negotiation may fail unexpectedly.
|
||||
* All future updates to the context negotiation interface implies that frontend must support
|
||||
* this environment call to query support.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_JIT_CAPABLE 74
|
||||
/* bool * --
|
||||
* Result is set to true if the frontend has already verified JIT can be
|
||||
* used, mainly for use iOS/tvOS. On other platforms the result is true.
|
||||
*/
|
||||
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# CMake policy settings shared between LLVM projects
|
||||
|
||||
# CMP0114: ExternalProject step targets fully adopt their steps.
|
||||
# New in CMake 3.19: https://cmake.org/cmake/help/latest/policy/CMP0114.html
|
||||
if(POLICY CMP0114)
|
||||
cmake_policy(SET CMP0114 OLD)
|
||||
endif()
|
||||
# CMP0116: Ninja generators transform `DEPFILE`s from `add_custom_command()`
|
||||
# New in CMake 3.20. https://cmake.org/cmake/help/latest/policy/CMP0116.html
|
||||
if(POLICY CMP0116)
|
||||
cmake_policy(SET CMP0116 OLD)
|
||||
endif()
|
||||
Loaded 100 of 769 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user