mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-31 05:15:55 -05:00
Compare commits
264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5b8021405 | ||
|
|
89abc8557f | ||
|
|
181a7c5b3d | ||
|
|
f79e2df11a | ||
|
|
be8c679d4a | ||
|
|
c577a42f62 | ||
|
|
ad69ac84b1 | ||
|
|
64a30a45d5 | ||
|
|
691df0fc83 | ||
|
|
1a2a926b77 | ||
|
|
da18428f27 | ||
|
|
5e86f62a98 | ||
|
|
e65021c85e | ||
|
|
83e26522b6 | ||
|
|
d011f37658 | ||
|
|
c07842d7ca | ||
|
|
4e7c3817ed | ||
|
|
68b203eb75 | ||
|
|
1bb0a72bed | ||
|
|
7685a22c5f | ||
|
|
fc91c8e4b0 | ||
|
|
57084fd797 | ||
|
|
2b8a9db0f0 | ||
|
|
9badfc043b | ||
|
|
4ff25819c2 | ||
|
|
563ff5a774 | ||
|
|
b042b8327a | ||
|
|
971c8739ca | ||
|
|
26f4aa0d9f | ||
|
|
dc5e5344c5 | ||
|
|
b2d1568abb | ||
|
|
632f388ece | ||
|
|
632ca944de | ||
|
|
0bbd21f25a | ||
|
|
367c4ec9c8 | ||
|
|
5538307838 | ||
|
|
eba8c82699 | ||
|
|
be3ac26306 | ||
|
|
fc1ad592cb | ||
|
|
f725d763d1 | ||
|
|
c2fe9f0966 | ||
|
|
235f4e39b4 | ||
|
|
58cef2361b | ||
|
|
60649d1cba | ||
|
|
ea9457c08c | ||
|
|
7bf9634e6e | ||
|
|
4288f876e2 | ||
|
|
10ad239fb9 | ||
|
|
550392c8d6 | ||
|
|
32e05cc62f | ||
|
|
886c52b322 | ||
|
|
ba66005585 | ||
|
|
bfc835fc54 | ||
|
|
32d6ac2241 | ||
|
|
758cdd91f3 | ||
|
|
6e81ce152e | ||
|
|
e487fd7450 | ||
|
|
bd75b70d85 | ||
|
|
6ef96c5533 | ||
|
|
6fc62bac94 | ||
|
|
baecf66716 | ||
|
|
7476ae230c | ||
|
|
175e66a60e | ||
|
|
a1dc979217 | ||
|
|
fbdcd22117 | ||
|
|
d50fb8d17b | ||
|
|
83e42ddfd9 | ||
|
|
6c8a90720f | ||
|
|
e70ec10b0e | ||
|
|
b4401b7df1 | ||
|
|
f598421705 | ||
|
|
84ceb45129 | ||
|
|
fc93f8bd66 | ||
|
|
8a2afd1c05 | ||
|
|
33e9ad7775 | ||
|
|
2059ad82c3 | ||
|
|
c25aad552d | ||
|
|
896091b124 | ||
|
|
d2e6d8e4d9 | ||
|
|
285b79f31e | ||
|
|
d468893bb0 | ||
|
|
df24d1e1e9 | ||
|
|
65c56a887c | ||
|
|
ef556d07ed | ||
|
|
882849e73c | ||
|
|
49d3fe65a3 | ||
|
|
a6aafa8cd6 | ||
|
|
ba9227c1e0 | ||
|
|
e77f138514 | ||
|
|
64a0c3f6e2 | ||
|
|
fae8f0a8d5 | ||
|
|
f2cfc70eca | ||
|
|
55e6761bf1 | ||
|
|
1a765ee5ab | ||
|
|
e1ca84d89c | ||
|
|
2082781cf5 | ||
|
|
d28d6d1a1b | ||
|
|
a61c93e99c | ||
|
|
e65497ec3b | ||
|
|
50dd6405e9 | ||
|
|
79eb53eb0d | ||
|
|
05ca498343 | ||
|
|
fbd4bc337b | ||
|
|
89115bcdde | ||
|
|
954c0d5bda | ||
|
|
bf8924ae0c | ||
|
|
30b202cf0c | ||
|
|
84766d5f6e | ||
|
|
106e669512 | ||
|
|
4d6e6cf75a | ||
|
|
26e7e12f09 | ||
|
|
b469e68ddb | ||
|
|
2e5a51bb05 | ||
|
|
4ae55f69e1 | ||
|
|
d079b8c3bb | ||
|
|
33f0d59545 | ||
|
|
42c36279d1 | ||
|
|
b55c6fa3e1 | ||
|
|
3a39d3c532 | ||
|
|
f67e808d0b | ||
|
|
e1d0a057ff | ||
|
|
e829c407e3 | ||
|
|
94a02c4b6d | ||
|
|
4792a29fac | ||
|
|
27c8e19c14 | ||
|
|
866c87b2bf | ||
|
|
aa4ce01c73 | ||
|
|
d0a5c144e6 | ||
|
|
5feb4dce51 | ||
|
|
4d4f223357 | ||
|
|
440e2d91fc | ||
|
|
bca73ef01e | ||
|
|
a032bfa0f5 | ||
|
|
ff8946b851 | ||
|
|
599b43db22 | ||
|
|
a4e4e01d2d | ||
|
|
8b3cd2d76d | ||
|
|
ffdaf0d16e | ||
|
|
b8d5e1e9c5 | ||
|
|
aa66d4b9e7 | ||
|
|
fdd2e1fcde | ||
|
|
591435761b | ||
|
|
4979c65566 | ||
|
|
f5fda76414 | ||
|
|
4b0d980d54 | ||
|
|
46ee3f0faa | ||
|
|
564ae6dd8c | ||
|
|
8aec382440 | ||
|
|
a99f8f78d0 | ||
|
|
0faea9d7c7 | ||
|
|
c294619102 | ||
|
|
f6bbfd7283 | ||
|
|
d3f493b6c2 | ||
|
|
bd8868d2c8 | ||
|
|
ee41a5a046 | ||
|
|
0033d9f4eb | ||
|
|
e5a793e8de | ||
|
|
3149183450 | ||
|
|
7c321a79c3 | ||
|
|
7c203e0635 | ||
|
|
ffd3efe5fa | ||
|
|
18dd754b31 | ||
|
|
3c97759aa7 | ||
|
|
f930b6e17d | ||
|
|
2d4f971d10 | ||
|
|
90267ec356 | ||
|
|
7fc53bf861 | ||
|
|
b9c2955b88 | ||
|
|
ed33dd0bb0 | ||
|
|
6d7f217e2a | ||
|
|
a83ca3c228 | ||
|
|
b9ec1a150d | ||
|
|
d9a4906b3c | ||
|
|
a83f87fbfa | ||
|
|
e9450b490f | ||
|
|
1588365d4a | ||
|
|
76e932ecc0 | ||
|
|
52c517d38d | ||
|
|
aac9bf3896 | ||
|
|
54891c6d8f | ||
|
|
d7238a5f80 | ||
|
|
0a6815da8f | ||
|
|
7631778edb | ||
|
|
1a3debd6c9 | ||
|
|
893b06c78b | ||
|
|
709f4b7e80 | ||
|
|
54fba5bf8b | ||
|
|
d977f1f988 | ||
|
|
2fea1975c2 | ||
|
|
5171bea0bf | ||
|
|
4e3b8111fd | ||
|
|
afcc01c3dc | ||
|
|
3a775e982f | ||
|
|
0f54a3a1f3 | ||
|
|
8500e4cba2 | ||
|
|
c1cdab72ef | ||
|
|
f4ae1fda6d | ||
|
|
aae3004f1f | ||
|
|
1aed960a38 | ||
|
|
6c4fdd146f | ||
|
|
04b56c3d4d | ||
|
|
1ed658bcdc | ||
|
|
8c0395bc7c | ||
|
|
cdc4f2db89 | ||
|
|
272b4b0cf8 | ||
|
|
10756c65a6 | ||
|
|
8524e93445 | ||
|
|
511ef3ef2b | ||
|
|
32ade6136b | ||
|
|
65d9509c38 | ||
|
|
ce9ce42c1c | ||
|
|
6343cb092b | ||
|
|
7cb26b1499 | ||
|
|
5d047a335d | ||
|
|
3e797eeea2 | ||
|
|
14bb98a519 | ||
|
|
a78d3f9977 | ||
|
|
2449b08f64 | ||
|
|
33d3bea472 | ||
|
|
c9c6f3aadb | ||
|
|
c9dbcbb3d3 | ||
|
|
924c816dbd | ||
|
|
695e11477e | ||
|
|
ac2a609d0a | ||
|
|
e3ae169833 | ||
|
|
25d6380963 | ||
|
|
f00b9f05ac | ||
|
|
b6881d2362 | ||
|
|
8e0349e2ac | ||
|
|
86c4c8fa96 | ||
|
|
33566137c2 | ||
|
|
f16bbfb469 | ||
|
|
b265d8e54a | ||
|
|
6a667d9493 | ||
|
|
ceed8c7420 | ||
|
|
d297b2d1cc | ||
|
|
39e74c627e | ||
|
|
28dea8e5bd | ||
|
|
a0c89858ed | ||
|
|
c6c3ca4d26 | ||
|
|
301418c728 | ||
|
|
730e67881b | ||
|
|
aec38328d0 | ||
|
|
050a71913a | ||
|
|
8cc6994dd0 | ||
|
|
f9909dab98 | ||
|
|
bc98556897 | ||
|
|
4f08ba3590 | ||
|
|
78cb0a2592 | ||
|
|
a5fac85727 | ||
|
|
8fdb60758b | ||
|
|
7510fa091e | ||
|
|
b87c32a94b | ||
|
|
b13494a192 | ||
|
|
d527675bda | ||
|
|
15cd2b693c | ||
|
|
cda883bb0f | ||
|
|
e03c91b888 | ||
|
|
9282f1fe75 | ||
|
|
af147b4f54 | ||
|
|
13b4201446 | ||
|
|
83bcbfebdd | ||
|
|
1a31b4aaff | ||
|
|
c280b16787 |
9
.gdbinit
Normal file
9
.gdbinit
Normal file
@@ -0,0 +1,9 @@
|
||||
# Skip all std:: and __gnu_debug:: symbols
|
||||
skip -rfu ^std::
|
||||
skip -rfu ^__gnu_debug::
|
||||
|
||||
# Skip all ImGui:: symbols
|
||||
skip -rfu ^ImGui::
|
||||
|
||||
# Trigger breakpoint when execution reaches triggerSafeShutdown()
|
||||
break triggerSafeShutdown
|
||||
187
.github/workflows/build.yml
vendored
187
.github/workflows/build.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -20,8 +20,6 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
env:
|
||||
CCACHE_DIR: "${{ github.workspace }}/.ccache"
|
||||
CCACHE_MAXSIZE: "1000M"
|
||||
CCACHE_COMPRESS: "true"
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v3
|
||||
@@ -32,16 +30,16 @@ jobs:
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
id: cache-ccache
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
max-size: 50M
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: 🟦 Install msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -51,7 +49,6 @@ jobs:
|
||||
gcc:p
|
||||
lld:p
|
||||
cmake:p
|
||||
make:p
|
||||
ccache:p
|
||||
glfw:p
|
||||
file:p
|
||||
@@ -59,6 +56,14 @@ jobs:
|
||||
freetype:p
|
||||
dlfcn:p
|
||||
libbacktrace:p
|
||||
ninja:p
|
||||
curl-winssl:p
|
||||
capstone:p
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- name: 📜 Set version variable
|
||||
run: |
|
||||
@@ -70,20 +75,19 @@ jobs:
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
cmake -G "MinGW Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCREATE_PACKAGE=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
|
||||
-DUSE_SYSTEM_CAPSTONE=ON \
|
||||
-DDOTNET_EXECUTABLE="C:/Program Files/dotnet/dotnet.exe" \
|
||||
..
|
||||
mingw32-make -j4 install
|
||||
ninja install
|
||||
cpack
|
||||
mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi
|
||||
|
||||
@@ -145,16 +149,16 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build
|
||||
max-size: 50M
|
||||
key: ${{ runner.os }}${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-ccache-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
key: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
@@ -166,13 +170,19 @@ jobs:
|
||||
run: |
|
||||
brew install glfw
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- name: 🧰 Checkout glfw
|
||||
if: ${{matrix.custom_glfw}}
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: glfw/glfw
|
||||
path: glfw
|
||||
|
||||
|
||||
# GLFW custom build (to allow software rendering)
|
||||
- name: ⬇️ Patch and install custom glfw
|
||||
if: ${{matrix.custom_glfw}}
|
||||
run: |
|
||||
@@ -182,17 +192,15 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
|
||||
..
|
||||
make -j 4 install
|
||||
ninja install
|
||||
|
||||
# MacOS cmake build
|
||||
- name: 🛠️ Build
|
||||
@@ -204,9 +212,8 @@ jobs:
|
||||
OBJC=$(brew --prefix llvm)/bin/clang \
|
||||
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
|
||||
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
|
||||
MACOSX_DEPLOYMENT_TARGET="10.10" \
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCREATE_BUNDLE=ON \
|
||||
-DCREATE_PACKAGE=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -217,10 +224,9 @@ jobs:
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET="10.10" \
|
||||
-DCPACK_PACKAGE_FILE_NAME="imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64" \
|
||||
..
|
||||
make -j4 package
|
||||
ninja package
|
||||
|
||||
- name: ⬆️ Upload DMG
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -230,9 +236,24 @@ jobs:
|
||||
|
||||
# Ubuntu build
|
||||
ubuntu:
|
||||
runs-on: ubuntu-22.04
|
||||
name: 🐧 Ubuntu 22.04
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: Ubuntu
|
||||
release_num: 22.04
|
||||
- name: Ubuntu
|
||||
release_num: 23.04
|
||||
|
||||
name: 🐧 Ubuntu ${{ matrix.release_num }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: "ubuntu:${{ matrix.release_num }}"
|
||||
options: --privileged
|
||||
|
||||
steps:
|
||||
- name: ⬇️ Install setup dependencies
|
||||
run: apt update && apt install -y git curl
|
||||
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v3
|
||||
@@ -242,39 +263,50 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
|
||||
max-size: 50M
|
||||
key: Ubuntu-${{matrix.release_num}}-${{ secrets.CACHE_VERSION }}-ccache-${{ github.run_id }}
|
||||
restore-keys: Ubuntu-${{matrix.release_num}}-${{ secrets.CACHE_VERSION }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
key: Ubuntu-${{matrix.release_num}}-${{ secrets.CACHE_VERSION }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo bash dist/get_deps_debian.sh
|
||||
apt update
|
||||
bash dist/get_deps_debian.sh
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
# Ubuntu cmake build
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
echo COMMIT_SHA_SHORT=$(git rev-parse --short HEAD) >> $GITHUB_ENV
|
||||
echo COMMIT_SHA_LONG=$(git rev-parse HEAD) >> $GITHUB_ENV
|
||||
echo COMMIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) >> $GITHUB_ENV
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DIMHEX_PATTERNS_PULL_MASTER=ON \
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${{ env.COMMIT_SHA_SHORT }}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${{ env.COMMIT_SHA_LONG}}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${{ env.COMMIT_BRANCH }}" \
|
||||
-DIMHEX_ENABLE_LTO=ON \
|
||||
-DIMHEX_USE_GTK_FILE_PICKER=ON \
|
||||
-DDOTNET_EXECUTABLE="dotnet" \
|
||||
..
|
||||
make -j 4 install DESTDIR=DebDir
|
||||
DESTDIR=DebDir ninja install
|
||||
|
||||
- name: 📜 Set version variable
|
||||
run: |
|
||||
@@ -284,12 +316,12 @@ jobs:
|
||||
run: |
|
||||
cp -r build/DEBIAN build/DebDir
|
||||
dpkg-deb -Zgzip --build build/DebDir
|
||||
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-22.04-x86_64.deb
|
||||
mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
|
||||
|
||||
- name: ⬆️ Upload DEB
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Ubuntu 22.04 DEB x86_64
|
||||
name: Ubuntu ${{ matrix.release_num }} DEB x86_64
|
||||
path: '*.deb'
|
||||
|
||||
# AppImage build
|
||||
@@ -306,23 +338,23 @@ jobs:
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ${{ runner.os }}-appimage-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-appimage-${{ secrets.CACHE_VERSION }}-build
|
||||
max-size: 50M
|
||||
key: appimage-${{ secrets.CACHE_VERSION }}-ccache-${{ github.run_id }}
|
||||
restore-keys: appimage-${{ secrets.CACHE_VERSION }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build-appimage/CMakeCache.txt
|
||||
key: ${{ runner.os }}-appimage-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
key: appimage-${{ secrets.CACHE_VERSION }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo bash dist/get_deps_debian.sh
|
||||
|
||||
sudo apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse
|
||||
sudo apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build
|
||||
sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool
|
||||
sudo chmod +x /usr/local/bin/appimagetool
|
||||
sudo pip3 install git+https://github.com/iTrooz/appimage-builder@dpkg-package-versions
|
||||
@@ -336,8 +368,8 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build-appimage
|
||||
cd build-appimage
|
||||
CC=gcc-12 CXX=g++-12 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
@@ -345,11 +377,10 @@ jobs:
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DIMHEX_ENABLE_LTO=ON \
|
||||
-DIMHEX_PLUGINS_IN_SHARE=ON \
|
||||
-DIMHEX_USE_BUNDLED_CA=ON \
|
||||
..
|
||||
make -j 4 install DESTDIR=AppDir
|
||||
DESTDIR=AppDir ninja install
|
||||
|
||||
- name: 📦 Bundle AppImage
|
||||
run: |
|
||||
@@ -395,31 +426,35 @@ jobs:
|
||||
run: |
|
||||
dist/get_deps_archlinux.sh --noconfirm
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: archlinux-${{ secrets.CACHE_VERSION }}-build
|
||||
max-size: 50M
|
||||
key: archlinux-${{ secrets.CACHE_VERSION }}-ccache-${{ github.run_id }}
|
||||
restore-keys: archlinux-${{ secrets.CACHE_VERSION }}-ccache
|
||||
max-size: 1G
|
||||
|
||||
- name: 📜 Restore CMakeCache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
build/CMakeCache.txt
|
||||
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
key: archlinux-${{ secrets.CACHE_VERSION }}-cmakecache-${{ hashFiles('**/CMakeLists.txt') }}
|
||||
|
||||
# ArchLinux cmake build
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc CXX=g++ cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
CC=gcc CXX=g++ cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DUSE_SYSTEM_CURL=ON \
|
||||
-DUSE_SYSTEM_FMT=ON \
|
||||
-DUSE_SYSTEM_YARA=ON \
|
||||
-DUSE_SYSTEM_NLOHMANN_JSON=ON \
|
||||
@@ -428,9 +463,10 @@ jobs:
|
||||
-DIMHEX_COMMIT_HASH_SHORT="${GITHUB_SHA::7}" \
|
||||
-DIMHEX_COMMIT_HASH_LONG="${GITHUB_SHA}" \
|
||||
-DIMHEX_COMMIT_BRANCH="${GITHUB_REF##*/}" \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DIMHEX_ENABLE_LTO=ON \
|
||||
-DIMHEX_USE_GTK_FILE_PICKER=ON \
|
||||
..
|
||||
make -j 4 install DESTDIR=installDir
|
||||
DESTDIR=installDir ninja install
|
||||
|
||||
- name: 📜 Set version variable
|
||||
run: |
|
||||
@@ -519,11 +555,16 @@ jobs:
|
||||
fedpkg \
|
||||
ccache
|
||||
|
||||
- name: ⬇️ Install .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- name: 📜 Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2.5
|
||||
with:
|
||||
key: rpm-${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: rpm-${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-build
|
||||
key: ${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-rpm-${{ github.run_id }}
|
||||
restore-keys: ${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-rpm
|
||||
max-size: 1G
|
||||
|
||||
- name: 📜 Set version variable
|
||||
@@ -566,7 +607,7 @@ jobs:
|
||||
path: /var/cache/mock
|
||||
key: ${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-mock-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-mock-
|
||||
${{ matrix.mock_release }}-${{ secrets.CACHE_VERSION }}-mock
|
||||
|
||||
# Fedora cmake build (in imhex.spec)
|
||||
- name: 📦 Build RPM
|
||||
|
||||
20
.github/workflows/release.yml
vendored
20
.github/workflows/release.yml
vendored
@@ -51,26 +51,6 @@ jobs:
|
||||
repo: ImHex-Patterns
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
- name: ✉️ Update C++ Plugin Template
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
env:
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
if: "${{ env.RELEASE_TOKEN != '' }}"
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
repository: WerWolv/ImHex-Cpp-Plugin-Template
|
||||
event-type: update_submodule
|
||||
|
||||
- name: ✉️ Update Rust Plugin Template
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
env:
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
if: "${{ env.RELEASE_TOKEN != '' }}"
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
repository: WerWolv/ImHex-Rust-Plugin-Template
|
||||
event-type: update_submodule
|
||||
|
||||
release-upload-artifacts:
|
||||
runs-on: ubuntu-latest
|
||||
name: Release Upload Artifacts
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -14,10 +14,6 @@
|
||||
path = lib/external/fmt
|
||||
url = https://github.com/fmtlib/fmt
|
||||
ignore = dirty
|
||||
[submodule "lib/external/curl"]
|
||||
path = lib/external/curl
|
||||
url = https://github.com/curl/curl
|
||||
ignore = dirty
|
||||
[submodule "lib/external/capstone"]
|
||||
path = lib/external/capstone
|
||||
url = https://github.com/capstone-engine/capstone
|
||||
@@ -31,4 +27,4 @@
|
||||
url = https://github.com/WerWolv/PatternLanguage
|
||||
[submodule "lib/external/libwolv"]
|
||||
path = lib/external/libwolv
|
||||
url = https://github.com/WerWolv/libwolv
|
||||
url = https://github.com/WerWolv/libwolv
|
||||
@@ -1,7 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# Options
|
||||
option(IMHEX_USE_BUNDLED_CA "Use the CA bundle in romfs instead of the system one" OFF)
|
||||
option(IMHEX_PLUGINS_IN_SHARE "Put the plugins in share/imhex/plugins instead of lib[..]/imhex/plugins" OFF)
|
||||
option(IMHEX_STRIP_RELEASE "Strip the release builds" ON)
|
||||
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
|
||||
@@ -10,6 +9,10 @@ option(IMHEX_PATTERNS_PULL_MASTER "Download latest files from master branch of t
|
||||
option(IMHEX_IGNORE_BAD_COMPILER "Allow compiling with an unsupported compiler" OFF)
|
||||
option(IMHEX_USE_GTK_FILE_PICKER "Use GTK file picker instead of xdg-desktop-portals" OFF)
|
||||
option(IMHEX_DISABLE_STACKTRACE "Disables support for printing stack traces" OFF)
|
||||
option(IMHEX_BUNDLE_DOTNET "Bundle .NET runtime" ON)
|
||||
option(IMHEX_ENABLE_LTO "Enables Link Time Optimizations if possible" OFF)
|
||||
option(IMHEX_USE_DEFAULT_BUILD_SETTINGS "Use default build settings" OFF)
|
||||
option(IMHEX_STRICT_WARNINGS "Enable most available warnings and treat them as errors" ON)
|
||||
|
||||
# Basic compiler and cmake configurations
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
@@ -21,6 +24,7 @@ include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
|
||||
# Setup project
|
||||
loadVersion(IMHEX_VERSION)
|
||||
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
|
||||
configureCMake()
|
||||
project(imhex
|
||||
LANGUAGES C CXX VERSION ${IMHEX_VERSION}
|
||||
DESCRIPTION "The ImHex Hex Editor"
|
||||
@@ -36,6 +40,7 @@ verifyCompiler()
|
||||
set(PLUGINS
|
||||
builtin
|
||||
windows
|
||||
script_loader
|
||||
)
|
||||
|
||||
# Add various defines
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_C_COMPILER": "gcc",
|
||||
"CMAKE_CXX_COMPILER": "g++",
|
||||
"CMAKE_C_COMPILER_LAUNCHER": "ccache",
|
||||
"CMAKE_CXX_COMPILER_LAUNCHER": "ccache",
|
||||
"CMAKE_C_FLAGS": "-fuse-ld=lld",
|
||||
"CMAKE_CXX_FLAGS": "-fuse-ld=lld",
|
||||
"IMHEX_PATTERNS_PULL_MASTER": "ON",
|
||||
"CMAKE_INSTALL_PREFIX": "./install",
|
||||
"USE_SYSTEM_CURL": "ON"
|
||||
"USE_SYSTEM_CAPSTONE": "ON",
|
||||
"IMHEX_USE_DEFAULT_BUILD_SETTINGS": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,9 +9,9 @@ To install plugins, simply download the relevant `.hexplug` file and drop it in
|
||||
(If you're developing a Plugin on your own, please feel free to add it to this list)
|
||||
|
||||
### Official Plugins
|
||||
- [Malcore Plugin](https://github.com/WerWolv/ImHex-Malcore-Plugin)
|
||||
- Direcly upload your files to https://malcore.io for advanced binary analysis.
|
||||
- [Extra Hashes Plugin](https://github.com/WerWolv/ImHex-Hashes-Plugin)
|
||||
- Adds support for a variety of new hashes to the Hashes view including Blake, Adler32, Murmur and Tiger
|
||||
- [Discord RPC Plugin](https://github.com/WerWolv/ImHex-Plugin-DiscordRPC)
|
||||
- Adds support for Discord Rich Presence
|
||||
|
||||
### Third-Party Plugins
|
||||
|
||||
10
README.md
10
README.md
@@ -120,7 +120,6 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
- Hexadecimal Color picker
|
||||
- Base converter
|
||||
- UNIX Permissions calculator
|
||||
- Anonfiles File upload tool
|
||||
- Wikipedia term definition finder
|
||||
- File utilities
|
||||
- File splitter
|
||||
@@ -145,7 +144,14 @@ For format patterns, libraries, magic and constant files, check out the [ImHex-P
|
||||
|
||||
To use ImHex, the following minimal system requirements need to be met:
|
||||
|
||||
- **OS**: Windows 7 or higher, macOS 10.15 (Catalina) or higher, "Modern" Linux (Ubuntu 22.04, Fedora 36/37, RHEL/AlmaLinux 9, and Arch Linux have official packages, other and older distributions can use the AppImage)
|
||||
- **OS**:
|
||||
- **Windows**: Windows 7 or higher (Windows 10/11 recommended)
|
||||
- **macOS**: macOS 11 (Big Sur) or higher,
|
||||
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases.
|
||||
- Ubuntu 22.04/23.04
|
||||
- Fedora 36/37
|
||||
- RHEL/AlmaLinux 9
|
||||
- Arch Linux
|
||||
- **CPU**: x86_64 (64 Bit)
|
||||
- **GPU**: OpenGL 3.0 or higher
|
||||
- Intel HD drivers are really buggy and often cause graphic artifacts
|
||||
|
||||
@@ -14,47 +14,6 @@ macro(addDefines)
|
||||
message(FATAL_ERROR "IMHEX_VERSION is not defined")
|
||||
endif ()
|
||||
|
||||
if (DEFINED IMHEX_COMMIT_HASH_LONG AND DEFINED IMHEX_COMMIT_HASH_SHORT AND DEFINED IMHEX_COMMIT_BRANCH)
|
||||
add_compile_definitions(
|
||||
GIT_COMMIT_HASH_LONG="${IMHEX_COMMIT_HASH_LONG}"
|
||||
GIT_COMMIT_HASH_SHORT="${IMHEX_COMMIT_HASH_SHORT}"
|
||||
GIT_BRANCH="${IMHEX_COMMIT_BRANCH}"
|
||||
)
|
||||
else()
|
||||
# Get the current working branch
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT_BRANCH
|
||||
)
|
||||
|
||||
# Get the latest abbreviated commit hash of the working branch
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%h --abbrev=7
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH_SHORT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT_HASH_SHORT
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%H
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH_LONG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT_HASH_LONG
|
||||
)
|
||||
|
||||
if (RESULT_BRANCH EQUAL 0 AND RESULT_HASH_LONG EQUAL 0 AND RESULT_HASH_SHORT EQUAL 0)
|
||||
add_compile_definitions(
|
||||
GIT_COMMIT_HASH_SHORT="${GIT_COMMIT_HASH_SHORT}"
|
||||
GIT_COMMIT_HASH_LONG="${GIT_COMMIT_HASH_LONG}"
|
||||
GIT_BRANCH="${GIT_BRANCH}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DPROJECT_VERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DPROJECT_VERSION_MINOR=${PROJECT_VERSION_MINOR} -DPROJECT_VERSION_PATCH=${PROJECT_VERSION_PATCH} ")
|
||||
|
||||
set(IMHEX_VERSION_STRING ${IMHEX_VERSION})
|
||||
@@ -65,16 +24,22 @@ macro(addDefines)
|
||||
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-Debug)
|
||||
add_compile_definitions(DEBUG _GLIBCXX_DEBUG _GLIBCXX_VERBOSE)
|
||||
elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-RelWithDebInfo)
|
||||
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING})
|
||||
add_compile_definitions(NDEBUG)
|
||||
elseif (CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
||||
set(IMHEX_VERSION_STRING ${IMHEX_VERSION_STRING}-MinSizeRel)
|
||||
add_compile_definitions(NDEBUG)
|
||||
endif ()
|
||||
|
||||
add_compile_definitions(IMHEX_VERSION="${IMHEX_VERSION_STRING}")
|
||||
endmacro()
|
||||
|
||||
function(addDefineToSource SOURCE DEFINE)
|
||||
set_property(
|
||||
SOURCE ${SOURCE}
|
||||
APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS "${DEFINE}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Detect current OS / System
|
||||
macro(detectOS)
|
||||
if (WIN32)
|
||||
@@ -82,10 +47,6 @@ macro(detectOS)
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
set(PLUGINS_INSTALL_LOCATION "plugins")
|
||||
|
||||
if (NOT USE_SYSTEM_CURL)
|
||||
SET(IMHEX_USE_BUNDLED_CA ON)
|
||||
endif ()
|
||||
elseif (APPLE)
|
||||
add_compile_definitions(OS_MACOS)
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
@@ -109,10 +70,6 @@ macro(detectOS)
|
||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||
endif()
|
||||
|
||||
if(IMHEX_USE_BUNDLED_CA)
|
||||
add_compile_definitions(IMHEX_USE_BUNDLED_CA)
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
# Detect 32 vs. 64 bit system
|
||||
@@ -135,7 +92,6 @@ macro(configurePackingResources)
|
||||
if (WIN32)
|
||||
set(APPLICATION_TYPE)
|
||||
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/resource.rc")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-subsystem,windows")
|
||||
|
||||
if (CREATE_PACKAGE)
|
||||
set(CPACK_GENERATOR "WIX")
|
||||
@@ -164,7 +120,7 @@ macro(configurePackingResources)
|
||||
set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/dist/macos/Info.plist.in")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.WerWolv.ImHex")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${GIT_COMMIT_HASH_SHORT}")
|
||||
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}-${IMHEX_COMMIT_HASH_SHORT}")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
|
||||
string(TIMESTAMP CURR_YEAR "%Y")
|
||||
@@ -297,6 +253,9 @@ macro(createPackage)
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
else()
|
||||
install(TARGETS main RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
if(WIN32) # Forwarder is only needed on Windows
|
||||
install(TARGETS imhex-forwarder BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (CREATE_PACKAGE)
|
||||
@@ -318,6 +277,75 @@ function(JOIN OUTPUT GLUE)
|
||||
set(${OUTPUT} "${_TMP_RESULT}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
macro(configureCMake)
|
||||
message(STATUS "Configuring ImHex v${IMHEX_VERSION}")
|
||||
|
||||
# Enable C and C++ languages
|
||||
enable_language(C CXX)
|
||||
|
||||
# Configure use of recommended build tools
|
||||
if (IMHEX_USE_DEFAULT_BUILD_SETTINGS)
|
||||
message(STATUS "Configuring CMake to use recommended build tools...")
|
||||
|
||||
find_program(CCACHE_PATH ccache)
|
||||
find_program(NINJA_PATH ninja)
|
||||
find_program(LD_LLD_PATH ld.lld)
|
||||
find_program(AR_LLVMLIBS_PATH llvm-ar)
|
||||
find_program(RANLIB_LLVMLIBS_PATH llvm-ranlib)
|
||||
|
||||
if (CCACHE_PATH)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PATH})
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PATH})
|
||||
else ()
|
||||
message(WARNING "ccache not found!")
|
||||
endif ()
|
||||
|
||||
if (AR_LLVMLIBS_PATH)
|
||||
set(CMAKE_AR ${AR_LLVMLIBS_PATH})
|
||||
else ()
|
||||
message(WARNING "llvm-ar not found, using default ar!")
|
||||
endif ()
|
||||
|
||||
if (RANLIB_LLVMLIBS_PATH)
|
||||
set(CMAKE_RANLIB ${RANLIB_LLVMLIBS_PATH})
|
||||
else ()
|
||||
message(WARNING "llvm-ranlib not found, using default ranlib!")
|
||||
endif ()
|
||||
|
||||
if (LD_LLD_PATH)
|
||||
set(CMAKE_LINKER ${LD_LLD_PATH})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
|
||||
else ()
|
||||
message(WARNING "lld not found, using default linker!")
|
||||
endif ()
|
||||
|
||||
if (NINJA_PATH)
|
||||
set(CMAKE_GENERATOR Ninja)
|
||||
else ()
|
||||
message(WARNING "ninja not found, using default generator!")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
# Enable LTO if desired and supported
|
||||
if (IMHEX_ENABLE_LTO)
|
||||
include(CheckIPOSupported)
|
||||
|
||||
check_ipo_supported(RESULT result OUTPUT output_error)
|
||||
if (result)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
message(STATUS "LTO enabled!")
|
||||
else ()
|
||||
message(WARNING "LTO is not supported: ${output_error}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Some libraries we use set the BUILD_SHARED_LIBS variable to ON, which causes CMake to
|
||||
# display a warning about options being set using set() instead of option().
|
||||
# Explicitly set the policy to NEW to suppress the warning.
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
endmacro()
|
||||
|
||||
macro(setDefaultBuiltTypeIfUnset)
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Using Release build type as it was left unset" FORCE)
|
||||
@@ -355,8 +383,8 @@ function(verifyCompiler)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0.0")
|
||||
message(FATAL_ERROR "ImHex requires GCC 12.0.0 or newer. Please use the latest GCC version.")
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0.0")
|
||||
message(FATAL_ERROR "ImHex requires Clang 14.0.0 or newer. Please use the latest Clang version.")
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "17.0.0")
|
||||
message(FATAL_ERROR "ImHex requires Clang 17.0.0 or newer. Please use the latest Clang version.")
|
||||
elseif (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
|
||||
message(FATAL_ERROR "ImHex can only be compiled with GCC or Clang. ${CMAKE_CXX_COMPILER_ID} is not supported.")
|
||||
endif()
|
||||
@@ -383,7 +411,7 @@ function(downloadImHexPatternsFiles dest)
|
||||
FetchContent_Declare(
|
||||
imhex_patterns
|
||||
GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git
|
||||
GIT_TAG master
|
||||
GIT_TAG origin/master
|
||||
)
|
||||
|
||||
message(STATUS "Downloading ImHex-Patterns repo branch ${PATTERNS_BRANCH}...")
|
||||
@@ -406,7 +434,10 @@ endfunction()
|
||||
|
||||
macro(setupCompilerFlags target)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(IMHEX_COMMON_FLAGS "-Wall -Wextra -Wpedantic -Werror")
|
||||
if (IMHEX_STRICT_WARNINGS)
|
||||
set(IMHEX_COMMON_FLAGS "-Wall -Wextra -Wpedantic -Werror")
|
||||
endif()
|
||||
|
||||
set(IMHEX_C_FLAGS "${IMHEX_COMMON_FLAGS} -Wno-array-bounds")
|
||||
set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
@@ -453,8 +484,6 @@ macro(addBundledLibraries)
|
||||
set_property(TARGET libwolv-net PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(XDGPP_INCLUDE_DIRS "${EXTERN_LIBS_FOLDER}/xdgpp")
|
||||
set(CURL_USE_MBEDTLS ON)
|
||||
set(BUILD_CURL_EXE OFF)
|
||||
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
|
||||
|
||||
if(NOT USE_SYSTEM_FMT)
|
||||
@@ -489,15 +518,8 @@ macro(addBundledLibraries)
|
||||
set(NLOHMANN_JSON_LIBRARIES nlohmann_json::nlohmann_json)
|
||||
endif()
|
||||
|
||||
if(NOT USE_SYSTEM_CURL)
|
||||
add_subdirectory(${EXTERN_LIBS_FOLDER}/curl EXCLUDE_FROM_ALL)
|
||||
set_target_properties(libcurl PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_compile_options(libcurl PRIVATE -Wno-deprecated-declarations)
|
||||
set(LIBCURL_LIBRARIES libcurl)
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.76.1)
|
||||
endif()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.60.0)
|
||||
|
||||
if (NOT USE_SYSTEM_LLVM)
|
||||
add_subdirectory(${EXTERN_LIBS_FOLDER}/llvm-demangle EXCLUDE_FROM_ALL)
|
||||
@@ -530,6 +552,7 @@ macro(addBundledLibraries)
|
||||
set(CAPSTONE_BUILD_TESTS OFF CACHE BOOL "Disable tests")
|
||||
add_subdirectory(${EXTERN_LIBS_FOLDER}/capstone EXCLUDE_FROM_ALL)
|
||||
set_target_properties(capstone PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_compile_options(capstone PRIVATE -Wno-unused-function)
|
||||
set(CAPSTONE_LIBRARIES "capstone")
|
||||
set(CAPSTONE_INCLUDE_DIRS ${EXTERN_LIBS_FOLDER}/capstone/include)
|
||||
else()
|
||||
@@ -537,10 +560,11 @@ macro(addBundledLibraries)
|
||||
pkg_search_module(CAPSTONE 4.0.2 REQUIRED capstone)
|
||||
endif()
|
||||
|
||||
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF)
|
||||
add_subdirectory(${EXTERN_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
|
||||
set_target_properties(libpl PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
find_package(mbedTLS 2.26.0 REQUIRED)
|
||||
find_package(mbedTLS 3.4.0 REQUIRED)
|
||||
|
||||
pkg_search_module(MAGIC libmagic>=5.39)
|
||||
if(NOT MAGIC_FOUND)
|
||||
@@ -587,11 +611,13 @@ function(generatePDBs)
|
||||
)
|
||||
FetchContent_Populate(cv2pdb)
|
||||
|
||||
set(PDBS_TO_GENERATE main libimhex ${PLUGINS})
|
||||
set(PDBS_TO_GENERATE main imhex-forwarder libimhex ${PLUGINS})
|
||||
add_custom_target(pdbs)
|
||||
foreach (PDB ${PDBS_TO_GENERATE})
|
||||
if (PDB STREQUAL "main")
|
||||
set(GENERATED_PDB imhex)
|
||||
elseif (PDB STREQUAL "imhex-forwarder")
|
||||
set(GENERATED_PDB imhex-gui)
|
||||
elseif (PDB STREQUAL "libimhex")
|
||||
set(GENERATED_PDB libimhex)
|
||||
else ()
|
||||
|
||||
81
cmake/modules/FindCoreClrEmbed.cmake
Normal file
81
cmake/modules/FindCoreClrEmbed.cmake
Normal file
@@ -0,0 +1,81 @@
|
||||
set(CoreClrEmbed_FOUND FALSE)
|
||||
|
||||
set(CORECLR_ARCH "linux-x64")
|
||||
set(CORECLR_SUBARCH "x64")
|
||||
if (WIN32)
|
||||
set(CORECLR_ARCH "win-x64")
|
||||
endif()
|
||||
if (UNIX)
|
||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
||||
set(CORECLR_ARCH "linux-arm64")
|
||||
set(CORECLR_SUBARCH "arm64")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT DOTNET_EXECUTABLE)
|
||||
set(DOTNET_EXECUTABLE dotnet)
|
||||
endif ()
|
||||
|
||||
set(CORECLR_VERSION "7.0")
|
||||
|
||||
execute_process(COMMAND ${DOTNET_EXECUTABLE} "--list-runtimes" OUTPUT_VARIABLE CORECLR_LIST_RUNTIMES_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (CORECLR_LIST_RUNTIMES_OUTPUT STREQUAL "")
|
||||
message(STATUS "Unable to find any .NET runtimes")
|
||||
return()
|
||||
endif ()
|
||||
|
||||
set(_ALL_RUNTIMES ${CORECLR_LIST_RUNTIMES_OUTPUT})
|
||||
string(REPLACE "\n" ";" _ALL_RUNTIMES_LIST ${_ALL_RUNTIMES})
|
||||
|
||||
foreach(X ${_ALL_RUNTIMES_LIST})
|
||||
string(REGEX MATCH "Microsoft\.NETCore\.App ([0-9]+)\.([0-9]+)\.([a-zA-Z0-9.-]+) [\[](.*)Microsoft\.NETCore\.App[\]]"
|
||||
CORECLR_VERSION_REGEX_MATCH ${X})
|
||||
|
||||
set(_RUNTIME_VERSION ${CMAKE_MATCH_1}.${CMAKE_MATCH_2})
|
||||
|
||||
if (CMAKE_MATCH_1 AND CMAKE_MATCH_4)
|
||||
if (${_RUNTIME_VERSION} STREQUAL ${CORECLR_VERSION})
|
||||
set(CORECLR_RUNTIME_VERSION ${_RUNTIME_VERSION})
|
||||
set(CORECLR_RUNTIME_VERSION_FULL ${CORECLR_VERSION}.${CMAKE_MATCH_3})
|
||||
set(CORECLR_RUNTIME_ROOT_PATH ${CMAKE_MATCH_4})
|
||||
message(STATUS "Found matching .NET runtime version '${CORECLR_RUNTIME_VERSION_FULL}' path='${CORECLR_RUNTIME_ROOT_PATH}'")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (CORECLR_RUNTIME_ROOT_PATH)
|
||||
get_filename_component(CORECLR_RUNTIME_ROOT_PATH ${CORECLR_RUNTIME_ROOT_PATH} DIRECTORY)
|
||||
endif()
|
||||
set(CoreClrEmbed_ROOT_PATH "${CORECLR_RUNTIME_ROOT_PATH}")
|
||||
|
||||
|
||||
file(GLOB _CORECLR_HOST_ARCH_PATH "${CORECLR_RUNTIME_ROOT_PATH}/packs/Microsoft.NETCore.App.Host.*-${CORECLR_SUBARCH}")
|
||||
if (_CORECLR_HOST_ARCH_PATH)
|
||||
get_filename_component(_CORECLR_HOST_ARCH_FILENAME ${_CORECLR_HOST_ARCH_PATH} NAME)
|
||||
string(REPLACE "Microsoft.NETCore.App.Host." "" _CORECLR_COMPUTED_ARCH "${_CORECLR_HOST_ARCH_FILENAME}")
|
||||
if (_CORECLR_COMPUTED_ARCH)
|
||||
set(CORECLR_ARCH "${_CORECLR_COMPUTED_ARCH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CORECLR_HOST_BASE_PATH "${CORECLR_RUNTIME_ROOT_PATH}/packs/Microsoft.NETCore.App.Host.${CORECLR_ARCH}/${CORECLR_RUNTIME_VERSION_FULL}")
|
||||
file(GLOB _CORECLR_FOUND_PATH ${CORECLR_HOST_BASE_PATH})
|
||||
if (_CORECLR_FOUND_PATH)
|
||||
set(CORECLR_NETHOST_ROOT "${_CORECLR_FOUND_PATH}/runtimes/${CORECLR_ARCH}/native")
|
||||
endif()
|
||||
|
||||
find_library(CoreClrEmbed_LIBRARY nethost PATHS
|
||||
${CORECLR_NETHOST_ROOT}
|
||||
)
|
||||
find_path(CoreClrEmbed_INCLUDE_DIR nethost.h PATHS
|
||||
${CORECLR_NETHOST_ROOT}
|
||||
)
|
||||
find_file(CoreClrEmbed_SHARED_LIBRARY nethost.dll nethost.so libnethost.so nethost.dylib libnethost.dylib PATHS
|
||||
${CORECLR_NETHOST_ROOT})
|
||||
|
||||
if (CoreClrEmbed_INCLUDE_DIR AND CoreClrEmbed_LIBRARY)
|
||||
set(CoreClrEmbed_FOUND TRUE)
|
||||
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}")
|
||||
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}")
|
||||
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}")
|
||||
endif()
|
||||
44
cmake/modules/ImHexPlugin.cmake
Normal file
44
cmake/modules/ImHexPlugin.cmake
Normal file
@@ -0,0 +1,44 @@
|
||||
macro(add_imhex_plugin)
|
||||
# Parse arguments
|
||||
set(options "")
|
||||
set(oneValueArgs NAME)
|
||||
set(multiValueArgs SOURCES INCLUDES LIBRARIES)
|
||||
cmake_parse_arguments(IMHEX_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
# Define new project for plugin
|
||||
project(${IMHEX_PLUGIN_NAME})
|
||||
|
||||
# Create a new shared library for the plugin source code
|
||||
add_library(${IMHEX_PLUGIN_NAME} SHARED ${IMHEX_PLUGIN_SOURCES})
|
||||
|
||||
# Add include directories and link libraries
|
||||
target_include_directories(${IMHEX_PLUGIN_NAME} PRIVATE ${IMHEX_PLUGIN_INCLUDES})
|
||||
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} ${IMHEX_PLUGIN_LIBRARIES})
|
||||
|
||||
# Add IMHEX_PROJECT_NAME and IMHEX_VERSION define
|
||||
target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}")
|
||||
target_compile_definitions(${IMHEX_PLUGIN_NAME} PRIVATE IMHEX_VERSION="${IMHEX_VERSION_STRING}")
|
||||
|
||||
# Enable required compiler flags
|
||||
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
setupCompilerFlags(${IMHEX_PLUGIN_NAME})
|
||||
|
||||
# Configure build properties
|
||||
set_target_properties(${IMHEX_PLUGIN_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
|
||||
CXX_STANDARD 23
|
||||
PREFIX ""
|
||||
SUFFIX ".hexplug"
|
||||
)
|
||||
|
||||
# Setup a romfs for the plugin
|
||||
set(LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/romfs)
|
||||
set(LIBROMFS_PROJECT_NAME ${IMHEX_PLUGIN_NAME})
|
||||
add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs)
|
||||
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
|
||||
|
||||
# Add the new plugin to the main dependency list so it gets built by default
|
||||
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
|
||||
endmacro()
|
||||
@@ -15,7 +15,9 @@ if(CMAKE_GENERATOR)
|
||||
set(_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}")
|
||||
function(postprocess_bundle out_target in_target)
|
||||
add_custom_command(TARGET ${out_target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -DBUNDLE_PATH="$<TARGET_FILE_DIR:${in_target}>/../.." -DCODE_SIGN_CERTIFICATE_ID="${CODE_SIGN_CERTIFICATE_ID}"
|
||||
COMMAND ${CMAKE_COMMAND} -DBUNDLE_PATH="$<TARGET_FILE_DIR:${in_target}>/../.."
|
||||
-DCODE_SIGN_CERTIFICATE_ID="${CODE_SIGN_CERTIFICATE_ID}"
|
||||
-DEXTRA_BUNDLE_LIBRARY_PATHS="${EXTRA_BUNDLE_LIBRARY_PATHS}"
|
||||
-P "${_POSTPROCESS_BUNDLE_MODULE_LOCATION}"
|
||||
)
|
||||
endfunction()
|
||||
@@ -29,13 +31,13 @@ message(STATUS "Fixing up application bundle: ${BUNDLE_PATH}")
|
||||
# Make sure to fix up any included ImHex plugin.
|
||||
file(GLOB_RECURSE extra_libs "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug")
|
||||
|
||||
message(STATUS "Fixing up application bundle: ${extra_dirs}")
|
||||
|
||||
# BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which
|
||||
# makes it sometimes break on libraries that do weird things with @rpath. Specify
|
||||
# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625
|
||||
# is fixed and in our minimum CMake version.
|
||||
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib")
|
||||
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib" ${EXTRA_BUNDLE_LIBRARY_PATHS})
|
||||
message(STATUS "Fixing up application bundle: ${extra_dirs}")
|
||||
|
||||
# BundleUtilities is overly verbose, so disable most of its messages
|
||||
function(message)
|
||||
|
||||
1
dist/AppImageBuilder.yml
vendored
1
dist/AppImageBuilder.yml
vendored
@@ -64,6 +64,7 @@ AppDir:
|
||||
- /lib/x86_64-linux-gnu/libbsd.so.0
|
||||
- /lib/x86_64-linux-gnu/libcairo-gobject.so.2
|
||||
- /lib/x86_64-linux-gnu/libcairo.so.2
|
||||
- /lib/x86_64-linux-gnu/libcurl-gnutls.so.4
|
||||
- /lib/x86_64-linux-gnu/libdatrie.so.1
|
||||
- /lib/x86_64-linux-gnu/libedit.so.2
|
||||
- /lib/x86_64-linux-gnu/libelf.so.1
|
||||
|
||||
2
dist/Arch/PKGBUILD
vendored
2
dist/Arch/PKGBUILD
vendored
@@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
|
||||
arch=("x86_64")
|
||||
url="https://github.com/WerWolv/ImHex"
|
||||
license=('GPL2')
|
||||
depends=(glfw mbedtls freetype2 libglvnd dbus xdg-desktop-portal curl fmt yara nlohmann-json)
|
||||
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json)
|
||||
makedepends=(git)
|
||||
provides=(imhex)
|
||||
conflicts=(imhex)
|
||||
|
||||
2
dist/Brewfile
vendored
2
dist/Brewfile
vendored
@@ -5,6 +5,8 @@ brew "ccache"
|
||||
brew "freetype2"
|
||||
brew "libmagic"
|
||||
brew "pkg-config"
|
||||
brew "curl"
|
||||
brew "gcc@12"
|
||||
brew "llvm"
|
||||
brew "glfw"
|
||||
brew "ninja"
|
||||
1
dist/Dockerfile
vendored
1
dist/Dockerfile
vendored
@@ -14,6 +14,7 @@ RUN pacman -S --needed --noconfirm \
|
||||
file \
|
||||
mbedtls \
|
||||
freetype2 \
|
||||
curl \
|
||||
dbus \
|
||||
xdg-desktop-portal
|
||||
|
||||
|
||||
15
dist/compiling/windows.md
vendored
15
dist/compiling/windows.md
vendored
@@ -7,22 +7,19 @@ On Windows, ImHex is built through [msys2 / mingw](https://www.msys2.org/)'s gcc
|
||||
3. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules`
|
||||
4. Install all the dependencies using `./ImHex/dist/get_deps_msys2.sh`
|
||||
5. Build ImHex itself using the following commands:
|
||||
|
||||
```sh
|
||||
cd ImHex
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "MinGW Makefiles" \
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
|
||||
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$USERPROFILE/.cargo/bin/" \
|
||||
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
|
||||
..
|
||||
mingw32-make -j install
|
||||
ninja install
|
||||
```
|
||||
|
||||
ImHex will look for any extra resources either in various folders directly next to the executable or in `%localappdata%/imhex`
|
||||
|
||||
For low RAM-usage system, you can use `mingw32-make -j N install` instead, to reduce RAM usage at compile time. Where `N` is amount of jobs you are willling to run at once. Roughly ~1 GB of RAM usage per job.
|
||||
|
||||
5
dist/get_deps_archlinux.sh
vendored
5
dist/get_deps_archlinux.sh
vendored
@@ -9,8 +9,9 @@ pacman -S $@ --needed \
|
||||
mbedtls \
|
||||
freetype2 \
|
||||
dbus \
|
||||
xdg-desktop-portal \
|
||||
gtk3 \
|
||||
curl \
|
||||
fmt \
|
||||
yara \
|
||||
nlohmann-json
|
||||
nlohmann-json \
|
||||
ninja
|
||||
|
||||
5
dist/get_deps_debian.sh
vendored
5
dist/get_deps_debian.sh
vendored
@@ -13,7 +13,6 @@ apt install -y \
|
||||
lld \
|
||||
${PKGCONF:-} \
|
||||
cmake \
|
||||
make \
|
||||
ccache \
|
||||
libglfw3-dev \
|
||||
libglm-dev \
|
||||
@@ -21,4 +20,6 @@ apt install -y \
|
||||
libmbedtls-dev \
|
||||
libfreetype-dev \
|
||||
libdbus-1-dev \
|
||||
xdg-desktop-portal
|
||||
libcurl4-gnutls-dev \
|
||||
libgtk-3-dev \
|
||||
ninja-build
|
||||
|
||||
4
dist/get_deps_fedora.sh
vendored
4
dist/get_deps_fedora.sh
vendored
@@ -5,9 +5,11 @@ dnf install -y \
|
||||
dbus-devel \
|
||||
file-devel \
|
||||
freetype-devel \
|
||||
libcurl-devel \
|
||||
gcc-c++ \
|
||||
git \
|
||||
mesa-libGL-devel \
|
||||
glfw-devel \
|
||||
lld \
|
||||
mbedtls-devel
|
||||
mbedtls-devel \
|
||||
gtk3-devel
|
||||
6
dist/get_deps_msys2.sh
vendored
6
dist/get_deps_msys2.sh
vendored
@@ -4,10 +4,12 @@ pacman -S --needed --noconfirm \
|
||||
mingw-w64-x86_64-gcc \
|
||||
mingw-w64-x86_64-lld \
|
||||
mingw-w64-x86_64-cmake \
|
||||
mingw-w64-x86_64-make \
|
||||
mingw-w64-x86_64-ccache \
|
||||
mingw-w64-x86_64-glfw \
|
||||
mingw-w64-x86_64-file \
|
||||
mingw-w64-x86_64-curl-winssl \
|
||||
mingw-w64-x86_64-mbedtls \
|
||||
mingw-w64-x86_64-freetype \
|
||||
mingw-w64-x86_64-dlfcn
|
||||
mingw-w64-x86_64-dlfcn \
|
||||
mingw-w64-x86_64-ninja \
|
||||
mingw-w64-x86_64-capstone
|
||||
|
||||
5
dist/rpm/imhex.spec
vendored
5
dist/rpm/imhex.spec
vendored
@@ -26,6 +26,7 @@ BuildRequires: llvm-devel
|
||||
BuildRequires: mbedtls-devel
|
||||
BuildRequires: yara-devel
|
||||
BuildRequires: nativefiledialog-extended-devel
|
||||
BuildRequires: dotnet-sdk-7.0
|
||||
%if 0%{?rhel}
|
||||
BuildRequires: gcc-toolset-12
|
||||
%endif
|
||||
@@ -74,10 +75,10 @@ CXXFLAGS+=" -std=gnu++2b"
|
||||
-D IMHEX_OFFLINE_BUILD=ON \
|
||||
-D USE_SYSTEM_NLOHMANN_JSON=ON \
|
||||
-D USE_SYSTEM_FMT=ON \
|
||||
-D USE_SYSTEM_CURL=ON \
|
||||
-D USE_SYSTEM_LLVM=ON \
|
||||
-D USE_SYSTEM_YARA=ON \
|
||||
-D USE_SYSTEM_NFD=ON \
|
||||
-D IMHEX_USE_GTK_FILE_PICKER=ON \
|
||||
-D IMHEX_BUNDLE_DOTNET=OFF \
|
||||
# when capstone >= 5.x is released we should be able to build against \
|
||||
# system libs of it \
|
||||
# -D USE_SYSTEM_CAPSTONE=ON
|
||||
|
||||
2
lib/external/capstone
vendored
2
lib/external/capstone
vendored
Submodule lib/external/capstone updated: d5141c0478...650e85dcf2
1
lib/external/curl
vendored
1
lib/external/curl
vendored
Submodule lib/external/curl deleted from b16d1fa8ee
2
lib/external/fmt
vendored
2
lib/external/fmt
vendored
Submodule lib/external/fmt updated: a0b8a92e3d...f5e54359df
6
lib/external/imgui/include/imconfig.h
vendored
6
lib/external/imgui/include/imconfig.h
vendored
@@ -14,10 +14,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
namespace hex::log::impl {
|
||||
void assertionHandler(bool expr, const char* expr_str, const char* file, int line);
|
||||
}
|
||||
#define IM_ASSERT(_EXPR) hex::log::impl::assertionHandler(_EXPR, #_EXPR, __FILE__, __LINE__)
|
||||
|
||||
//---- 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.
|
||||
|
||||
@@ -636,8 +636,10 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
|
||||
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
|
||||
{
|
||||
ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
|
||||
if (src_tmp.GlyphsCount == 0)
|
||||
continue;
|
||||
// IMHEX PATCH BEGIN
|
||||
// if (src_tmp.GlyphsCount == 0)
|
||||
// continue;
|
||||
// IMHEX PATCH END
|
||||
|
||||
// When merging fonts with MergeMode=true:
|
||||
// - We can have multiple input fonts writing into a same destination font.
|
||||
|
||||
5
lib/external/imgui/source/TextEditor.cpp
vendored
5
lib/external/imgui/source/TextEditor.cpp
vendored
@@ -202,8 +202,6 @@ void TextEditor::DeleteRange(const Coordinates &aStart, const Coordinates &aEnd)
|
||||
}
|
||||
|
||||
int TextEditor::InsertTextAt(Coordinates & /* inout */ aWhere, const char *aValue) {
|
||||
assert(!mReadOnly);
|
||||
|
||||
int cindex = GetCharacterIndex(aWhere);
|
||||
int totalLines = 0;
|
||||
while (*aValue != '\0') {
|
||||
@@ -541,8 +539,6 @@ void TextEditor::RemoveLine(int aIndex) {
|
||||
}
|
||||
|
||||
TextEditor::Line &TextEditor::InsertLine(int aIndex) {
|
||||
assert(!mReadOnly);
|
||||
|
||||
auto &result = *mLines.insert(mLines.begin() + aIndex, Line());
|
||||
|
||||
ErrorMarkers etmp;
|
||||
@@ -990,7 +986,6 @@ void TextEditor::Render() {
|
||||
|
||||
if (mScrollToCursor) {
|
||||
EnsureCursorVisible();
|
||||
ImGui::SetWindowFocus();
|
||||
mScrollToCursor = false;
|
||||
}
|
||||
}
|
||||
|
||||
29
lib/external/imgui/source/imgui_impl_glfw.cpp
vendored
29
lib/external/imgui/source/imgui_impl_glfw.cpp
vendored
@@ -824,34 +824,7 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||
|
||||
// IMHEX PATCH BEGIN
|
||||
#if defined(_WIN32)
|
||||
switch (imgui_cursor) {
|
||||
case ImGuiMouseCursor_Hand:
|
||||
SetCursor(LoadCursor(nullptr, IDC_HAND));
|
||||
break;
|
||||
case ImGuiMouseCursor_ResizeEW:
|
||||
SetCursor(LoadCursor(nullptr, IDC_SIZEWE));
|
||||
break;
|
||||
case ImGuiMouseCursor_ResizeNS:
|
||||
SetCursor(LoadCursor(nullptr, IDC_SIZENS));
|
||||
break;
|
||||
case ImGuiMouseCursor_ResizeNWSE:
|
||||
SetCursor(LoadCursor(nullptr, IDC_SIZENWSE));
|
||||
break;
|
||||
case ImGuiMouseCursor_ResizeNESW:
|
||||
SetCursor(LoadCursor(nullptr, IDC_SIZENESW));
|
||||
break;
|
||||
case ImGuiMouseCursor_ResizeAll:
|
||||
SetCursor(LoadCursor(nullptr, IDC_SIZEALL));
|
||||
break;
|
||||
case ImGuiMouseCursor_NotAllowed:
|
||||
SetCursor(LoadCursor(nullptr, IDC_NO));
|
||||
break;
|
||||
case ImGuiMouseCursor_TextInput:
|
||||
SetCursor(LoadCursor(nullptr, IDC_IBEAM));
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#if !defined(_WIN32)
|
||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
#endif
|
||||
|
||||
|
||||
2
lib/external/libromfs
vendored
2
lib/external/libromfs
vendored
Submodule lib/external/libromfs updated: 80b9adea20...31b331c02a
2
lib/external/libwolv
vendored
2
lib/external/libwolv
vendored
Submodule lib/external/libwolv updated: 128bed69ea...094d87ca30
84796
lib/external/miniaudio/include/miniaudio.h
vendored
84796
lib/external/miniaudio/include/miniaudio.h
vendored
File diff suppressed because it is too large
Load Diff
80171
lib/external/miniaudio/source/miniaudio.c
vendored
80171
lib/external/miniaudio/source/miniaudio.c
vendored
File diff suppressed because it is too large
Load Diff
2
lib/external/nativefiledialog
vendored
2
lib/external/nativefiledialog
vendored
Submodule lib/external/nativefiledialog updated: 7909f55d91...800f58283f
11412
lib/external/nlohmann_json/include/nlohmann/json.hpp
vendored
11412
lib/external/nlohmann_json/include/nlohmann/json.hpp
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,11 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
@@ -7,13 +15,116 @@
|
||||
#include <string> // string
|
||||
#include <vector> // vector
|
||||
|
||||
// #include <nlohmann/detail/abi_macros.hpp>
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
|
||||
// This file contains all macro definitions affecting or depending on the ABI
|
||||
|
||||
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
|
||||
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
|
||||
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
|
||||
#warning "Already included a different version of the library!"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
|
||||
|
||||
#ifndef JSON_DIAGNOSTICS
|
||||
#define JSON_DIAGNOSTICS 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
|
||||
#endif
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
|
||||
#endif
|
||||
|
||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
|
||||
#endif
|
||||
|
||||
// Construct the namespace ABI tags component
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
||||
|
||||
#define NLOHMANN_JSON_ABI_TAGS \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
|
||||
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||
|
||||
// Construct the namespace version component
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
||||
_v ## major ## _ ## minor ## _ ## patch
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
||||
|
||||
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
||||
#else
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
|
||||
NLOHMANN_JSON_VERSION_MINOR, \
|
||||
NLOHMANN_JSON_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
// Combine namespace components
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE
|
||||
#define NLOHMANN_JSON_NAMESPACE \
|
||||
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION)
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||
namespace nlohmann \
|
||||
{ \
|
||||
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION) \
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
||||
#define NLOHMANN_JSON_NAMESPACE_END \
|
||||
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
||||
} // namespace nlohmann
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@since version 1.0.0
|
||||
*/
|
||||
namespace nlohmann
|
||||
{
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
/*!
|
||||
@brief default JSONSerializer template argument
|
||||
|
||||
@@ -24,6 +135,8 @@ for serialization.
|
||||
template<typename T = void, typename SFINAE = void>
|
||||
struct adl_serializer;
|
||||
|
||||
/// a class to store JSON values
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||
template<template<typename U, typename V, typename... Args> class ObjectType =
|
||||
std::map,
|
||||
template<typename U, typename... Args> class ArrayType = std::vector,
|
||||
@@ -37,42 +150,26 @@ template<template<typename U, typename V, typename... Args> class ObjectType =
|
||||
class BinaryType = std::vector<std::uint8_t>>
|
||||
class basic_json;
|
||||
|
||||
/*!
|
||||
@brief JSON Pointer
|
||||
|
||||
A JSON pointer defines a string syntax for identifying a specific value
|
||||
within a JSON document. It can be used with functions `at` and
|
||||
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
|
||||
|
||||
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||
template<typename RefStringType>
|
||||
class json_pointer;
|
||||
|
||||
/*!
|
||||
@brief default JSON class
|
||||
|
||||
This type is the default specialization of the @ref basic_json class which
|
||||
uses the standard template types.
|
||||
|
||||
@since version 1.0.0
|
||||
@brief default specialization
|
||||
@sa https://json.nlohmann.me/api/json/
|
||||
*/
|
||||
using json = basic_json<>;
|
||||
|
||||
/// @brief a minimal map-like container that preserves insertion order
|
||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||
struct ordered_map;
|
||||
|
||||
/*!
|
||||
@brief ordered JSON class
|
||||
|
||||
This type preserves the insertion order of object keys.
|
||||
|
||||
@since version 3.9.0
|
||||
*/
|
||||
/// @brief specialization that maintains the insertion order of object keys
|
||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||
using ordered_json = basic_json<nlohmann::ordered_map>;
|
||||
|
||||
} // namespace nlohmann
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
Submodule lib/external/pattern_language updated: 57dc02b9d3...ff92cf631a
7
lib/external/yara/CMakeLists.txt
vendored
7
lib/external/yara/CMakeLists.txt
vendored
@@ -114,7 +114,9 @@ target_compile_definitions(libyara PRIVATE
|
||||
HASH_MODULE DOTNET_MODULE MAGIC_MODULE MACHO_MODULE DEX_MODULE
|
||||
)
|
||||
|
||||
target_compile_options(libyara PRIVATE -Wno-shift-count-overflow -Wno-stringop-overflow)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(libyara PRIVATE -Wno-shift-count-overflow -Wno-stringop-overflow)
|
||||
endif ()
|
||||
|
||||
target_include_directories(
|
||||
libyara
|
||||
@@ -131,6 +133,5 @@ else ()
|
||||
endif ()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yara/yara.pc.in
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/yara/yara.pc @ONLY)
|
||||
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
|
||||
2
lib/external/yara/yara
vendored
2
lib/external/yara/yara
vendored
Submodule lib/external/yara/yara updated: 96790e56fc...d1ff3ecc46
@@ -15,12 +15,14 @@ set(LIBIMHEX_SOURCES
|
||||
source/api/project_file_manager.cpp
|
||||
source/api/theme_manager.cpp
|
||||
source/api/layout_manager.cpp
|
||||
source/api/achievement_manager.cpp
|
||||
|
||||
source/data_processor/attribute.cpp
|
||||
source/data_processor/link.cpp
|
||||
source/data_processor/node.cpp
|
||||
|
||||
source/helpers/utils.cpp
|
||||
source/helpers/utils_linux.cpp
|
||||
source/helpers/fs.cpp
|
||||
source/helpers/magic.cpp
|
||||
source/helpers/crypto.cpp
|
||||
@@ -37,6 +39,8 @@ set(LIBIMHEX_SOURCES
|
||||
source/ui/imgui_imhex_extensions.cpp
|
||||
source/ui/view.cpp
|
||||
source/ui/popup.cpp
|
||||
|
||||
source/subcommands/subcommands.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
@@ -58,11 +62,14 @@ add_library(libimhex SHARED ${LIBIMHEX_SOURCES})
|
||||
set_target_properties(libimhex PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
setupCompilerFlags(libimhex)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(libimhex)
|
||||
|
||||
target_include_directories(libimhex PUBLIC include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIRS} ${CAPSTONE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} ${YARA_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
|
||||
target_include_directories(libimhex PUBLIC include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ${CAPSTONE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} ${YARA_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
|
||||
target_link_directories(libimhex PUBLIC ${MBEDTLS_LIBRARY_DIR} ${CAPSTONE_LIBRARY_DIRS} ${MAGIC_LIBRARY_DIRS})
|
||||
|
||||
if (WIN32)
|
||||
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
|
||||
elseif (APPLE)
|
||||
find_library(FOUNDATION NAMES Foundation)
|
||||
@@ -70,4 +77,46 @@ elseif (APPLE)
|
||||
endif ()
|
||||
|
||||
target_link_libraries(libimhex PRIVATE ${FMT_LIBRARIES})
|
||||
target_link_libraries(libimhex PUBLIC dl imgui ${NFD_LIBRARIES} magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${LIBBACKTRACE_LIBRARIES} libpl libpl-gen ${MINIAUDIO_LIBRARIES} libwolv-utils libwolv-io libwolv-hash libwolv-net libwolv-containers)
|
||||
target_link_libraries(libimhex PUBLIC dl imgui ${NFD_LIBRARIES} magic ${CAPSTONE_LIBRARIES} LLVMDemangle microtar ${NLOHMANN_JSON_LIBRARIES} ${YARA_LIBRARIES} ${LIBCURL_LIBRARIES} ${MBEDTLS_LIBRARIES} ${LIBBACKTRACE_LIBRARIES} plcli libpl libpl-gen ${MINIAUDIO_LIBRARIES} libwolv-utils libwolv-io libwolv-hash libwolv-net libwolv-containers)
|
||||
|
||||
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
|
||||
|
||||
if (DEFINED IMHEX_COMMIT_HASH_LONG AND DEFINED IMHEX_COMMIT_HASH_SHORT AND DEFINED IMHEX_COMMIT_BRANCH)
|
||||
set(GIT_COMMIT_HASH_LONG "${IMHEX_COMMIT_HASH_LONG}")
|
||||
set(GIT_COMMIT_HASH_SHORT "${IMHEX_COMMIT_HASH_SHORT}")
|
||||
set(GIT_BRANCH "${IMHEX_COMMIT_BRANCH}")
|
||||
else()
|
||||
# Get the current working branch
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT_BRANCH
|
||||
)
|
||||
|
||||
# Get the latest abbreviated commit hash of the working branch
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%h --abbrev=7
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH_SHORT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT_HASH_SHORT
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%H
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH_LONG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE RESULT_HASH_LONG
|
||||
)
|
||||
endif ()
|
||||
|
||||
if ((NOT GIT_COMMIT_HASH_SHORT STREQUAL "") AND (NOT GIT_COMMIT_HASH_LONG STREQUAL "") AND (NOT GIT_BRANCH STREQUAL ""))
|
||||
addDefineToSource(source/api/imhex_api.cpp "GIT_COMMIT_HASH_SHORT=\"${GIT_COMMIT_HASH_SHORT}\"")
|
||||
addDefineToSource(source/api/imhex_api.cpp "GIT_COMMIT_HASH_LONG=\"${GIT_COMMIT_HASH_LONG}\"")
|
||||
addDefineToSource(source/api/imhex_api.cpp "GIT_BRANCH=\"${GIT_BRANCH}\"")
|
||||
endif ()
|
||||
|
||||
addDefineToSource(source/api/imhex_api.cpp "IMHEX_VERSION=\"${IMHEX_VERSION_STRING}\"")
|
||||
412
lib/libimhex/include/hex/api/achievement_manager.hpp
Normal file
412
lib/libimhex/include/hex/api/achievement_manager.hpp
Normal file
@@ -0,0 +1,412 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <span>
|
||||
|
||||
#include <hex/api/event.hpp>
|
||||
#include <imgui.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class AchievementManager;
|
||||
|
||||
class Achievement {
|
||||
public:
|
||||
explicit Achievement(std::string unlocalizedCategory, std::string unlocalizedName) : m_unlocalizedCategory(std::move(unlocalizedCategory)), m_unlocalizedName(std::move(unlocalizedName)) { }
|
||||
|
||||
/**
|
||||
* @brief Returns the unlocalized name of the achievement
|
||||
* @return Unlocalized name of the achievement
|
||||
*/
|
||||
[[nodiscard]] const std::string &getUnlocalizedName() const {
|
||||
return this->m_unlocalizedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the unlocalized category of the achievement
|
||||
* @return Unlocalized category of the achievement
|
||||
*/
|
||||
[[nodiscard]] const std::string &getUnlocalizedCategory() const {
|
||||
return this->m_unlocalizedCategory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether the achievement is unlocked
|
||||
* @return Whether the achievement is unlocked
|
||||
*/
|
||||
[[nodiscard]] bool isUnlocked() const {
|
||||
return this->m_progress == this->m_maxProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the description of the achievement
|
||||
* @param description Description of the achievement
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setDescription(std::string description) {
|
||||
this->m_unlocalizedDescription = std::move(description);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a requirement to the achievement. The achievement will only be unlockable if all requirements are unlocked.
|
||||
* @param requirement Unlocalized name of the requirement
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& addRequirement(std::string requirement) {
|
||||
this->m_requirements.emplace_back(std::move(requirement));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a visibility requirement to the achievement. The achievement will only be visible if all requirements are unlocked.
|
||||
* @param requirement Unlocalized name of the requirement
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& addVisibilityRequirement(std::string requirement) {
|
||||
this->m_visibilityRequirements.emplace_back(std::move(requirement));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Marks the achievement as blacked. Blacked achievements are visible but their name and description are hidden.
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setBlacked() {
|
||||
this->m_blacked = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Marks the achievement as invisible. Invisible achievements are not visible at all.
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setInvisible() {
|
||||
this->m_invisible = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether the achievement is blacked
|
||||
* @return Whether the achievement is blacked
|
||||
*/
|
||||
[[nodiscard]] bool isBlacked() const {
|
||||
return this->m_blacked;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether the achievement is invisible
|
||||
* @return Whether the achievement is invisible
|
||||
*/
|
||||
[[nodiscard]] bool isInvisible() const {
|
||||
return this->m_invisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the list of requirements of the achievement
|
||||
* @return List of requirements of the achievement
|
||||
*/
|
||||
[[nodiscard]] const std::vector<std::string> &getRequirements() const {
|
||||
return this->m_requirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the list of visibility requirements of the achievement
|
||||
* @return List of visibility requirements of the achievement
|
||||
*/
|
||||
[[nodiscard]] const std::vector<std::string> &getVisibilityRequirements() const {
|
||||
return this->m_visibilityRequirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the unlocalized description of the achievement
|
||||
* @return Unlocalized description of the achievement
|
||||
*/
|
||||
[[nodiscard]] const std::string &getUnlocalizedDescription() const {
|
||||
return this->m_unlocalizedDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the icon of the achievement
|
||||
* @return Icon of the achievement
|
||||
*/
|
||||
[[nodiscard]] const ImGui::Texture &getIcon() const {
|
||||
if (this->m_iconData.empty())
|
||||
return this->m_icon;
|
||||
|
||||
if (this->m_icon.isValid())
|
||||
return m_icon;
|
||||
|
||||
this->m_icon = ImGui::Texture(reinterpret_cast<const u8*>(this->m_iconData.data()), this->m_iconData.size());
|
||||
|
||||
return this->m_icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::span<const std::byte> data) {
|
||||
this->m_iconData.reserve(data.size());
|
||||
for (auto &byte : data)
|
||||
this->m_iconData.emplace_back(static_cast<u8>(byte));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::span<const u8> data) {
|
||||
this->m_iconData.assign(data.begin(), data.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(std::vector<u8> data) {
|
||||
this->m_iconData = std::move(data);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the icon of the achievement
|
||||
* @param data Icon data
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setIcon(const std::vector<std::byte> &data) {
|
||||
this->m_iconData.reserve(data.size());
|
||||
for (auto &byte : data)
|
||||
this->m_iconData.emplace_back(static_cast<u8>(byte));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specifies the required progress to unlock the achievement. This is the number of times this achievement has to be triggered to unlock it. The default is 1.
|
||||
* @param progress Required progress
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
Achievement& setRequiredProgress(u32 progress) {
|
||||
this->m_maxProgress = progress;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the required progress to unlock the achievement
|
||||
* @return Required progress to unlock the achievement
|
||||
*/
|
||||
[[nodiscard]] u32 getRequiredProgress() const {
|
||||
return this->m_maxProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current progress of the achievement
|
||||
* @return Current progress of the achievement
|
||||
*/
|
||||
[[nodiscard]] u32 getProgress() const {
|
||||
return this->m_progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the callback to call when the achievement is clicked
|
||||
* @param callback Callback to call when the achievement is clicked
|
||||
*/
|
||||
void setClickCallback(const std::function<void(Achievement &)> &callback) {
|
||||
this->m_clickCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the callback to call when the achievement is clicked
|
||||
* @return Callback to call when the achievement is clicked
|
||||
*/
|
||||
[[nodiscard]] const std::function<void(Achievement &)> &getClickCallback() const {
|
||||
return this->m_clickCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether the achievement is temporary. Temporary achievements have been added by challenge projects for example and will be removed when the project is closed.
|
||||
* @return Whether the achievement is temporary
|
||||
*/
|
||||
[[nodiscard]] bool isTemporary() const {
|
||||
return this->m_temporary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets whether the achievement is unlocked
|
||||
* @param unlocked Whether the achievement is unlocked
|
||||
*/
|
||||
void setUnlocked(bool unlocked) {
|
||||
if (unlocked) {
|
||||
if (this->m_progress < this->m_maxProgress)
|
||||
this->m_progress++;
|
||||
} else {
|
||||
this->m_progress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void setProgress(u32 progress) {
|
||||
this->m_progress = progress;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_unlocalizedCategory, m_unlocalizedName;
|
||||
std::string m_unlocalizedDescription;
|
||||
|
||||
bool m_blacked = false;
|
||||
bool m_invisible = false;
|
||||
std::vector<std::string> m_requirements, m_visibilityRequirements;
|
||||
|
||||
std::function<void(Achievement &)> m_clickCallback;
|
||||
|
||||
std::vector<u8> m_iconData;
|
||||
mutable ImGui::Texture m_icon;
|
||||
|
||||
u32 m_progress = 0;
|
||||
u32 m_maxProgress = 1;
|
||||
|
||||
bool m_temporary = false;
|
||||
|
||||
friend class AchievementManager;
|
||||
};
|
||||
|
||||
class AchievementManager {
|
||||
public:
|
||||
AchievementManager() = delete;
|
||||
|
||||
struct AchievementNode {
|
||||
Achievement *achievement;
|
||||
std::vector<AchievementNode*> children, parents;
|
||||
std::vector<AchievementNode*> visibilityParents;
|
||||
ImVec2 position;
|
||||
|
||||
[[nodiscard]] bool hasParents() const {
|
||||
return !this->parents.empty();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isUnlockable() const {
|
||||
return std::all_of(this->parents.begin(), this->parents.end(), [](auto &parent) { return parent->achievement->isUnlocked(); });
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isVisible() const {
|
||||
return std::all_of(this->visibilityParents.begin(), this->visibilityParents.end(), [](auto &parent) { return parent->achievement->isUnlocked(); });
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isUnlocked() const {
|
||||
return this->achievement->isUnlocked();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Adds a new achievement
|
||||
* @tparam T Type of the achievement
|
||||
* @param args Arguments to pass to the constructor of the achievement
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
template<std::derived_from<Achievement> T = Achievement>
|
||||
static Achievement& addAchievement(auto && ... args) {
|
||||
auto newAchievement = std::make_unique<T>(std::forward<decltype(args)>(args)...);
|
||||
|
||||
const auto &category = newAchievement->getUnlocalizedCategory();
|
||||
const auto &name = newAchievement->getUnlocalizedName();
|
||||
|
||||
auto [categoryIter, categoryInserted] = getAchievements().insert({ category, std::unordered_map<std::string, std::unique_ptr<Achievement>>{} });
|
||||
auto &[categoryKey, achievements] = *categoryIter;
|
||||
|
||||
auto [achievementIter, achievementInserted] = achievements.insert({ name, std::move(newAchievement) });
|
||||
auto &[achievementKey, achievement] = *achievementIter;
|
||||
|
||||
achievementAdded();
|
||||
|
||||
return *achievement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a new temporary achievement
|
||||
* @tparam T Type of the achievement
|
||||
* @param args Arguments to pass to the constructor of the achievement
|
||||
* @return Reference to the achievement
|
||||
*/
|
||||
template<std::derived_from<Achievement> T = Achievement>
|
||||
static Achievement& addTemporaryAchievement(auto && ... args) {
|
||||
auto &achievement = addAchievement(std::forward<decltype(args)>(args)...);
|
||||
|
||||
achievement.m_temporary = true;
|
||||
|
||||
return achievement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks an achievement
|
||||
* @param unlocalizedCategory Unlocalized category of the achievement
|
||||
* @param unlocalizedName Unlocalized name of the achievement
|
||||
*/
|
||||
static void unlockAchievement(const std::string &unlocalizedCategory, const std::string &unlocalizedName);
|
||||
|
||||
/**
|
||||
* @brief Returns all registered achievements
|
||||
* @return All achievements
|
||||
*/
|
||||
static std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>& getAchievements();
|
||||
|
||||
/**
|
||||
* @brief Returns all achievement start nodes
|
||||
* @note Start nodes are all nodes that don't have any parents
|
||||
* @param rebuild Whether to rebuild the list of start nodes
|
||||
* @return All achievement start nodes
|
||||
*/
|
||||
static std::unordered_map<std::string, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
|
||||
|
||||
/**
|
||||
* @brief Returns all achievement nodes
|
||||
* @param rebuild Whether to rebuild the list of nodes
|
||||
* @return All achievement nodes
|
||||
*/
|
||||
static std::unordered_map<std::string, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
|
||||
|
||||
/**
|
||||
* @brief Loads the progress of all achievements from the achievements save file
|
||||
*/
|
||||
static void loadProgress();
|
||||
|
||||
/**
|
||||
* @brief Stores the progress of all achievements to the achievements save file
|
||||
*/
|
||||
static void storeProgress();
|
||||
|
||||
/**
|
||||
* @brief Removes all registered achievements from the tree
|
||||
*/
|
||||
static void clear();
|
||||
|
||||
/**
|
||||
* @brief Removes all temporary achievements from the tree
|
||||
*/
|
||||
static void clearTemporary();
|
||||
|
||||
private:
|
||||
static void achievementAdded();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -258,6 +258,7 @@ namespace hex {
|
||||
};
|
||||
|
||||
std::map<std::string, Visualizer> &getVisualizers();
|
||||
std::map<std::string, Visualizer> &getInlineVisualizers();
|
||||
std::map<std::string, pl::api::PragmaHandler> &getPragmas();
|
||||
std::vector<impl::FunctionDefinition> &getFunctions();
|
||||
|
||||
@@ -317,6 +318,15 @@ namespace hex {
|
||||
*/
|
||||
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, u32 parameterCount);
|
||||
|
||||
/**
|
||||
* @brief Adds a new inline visualizer to the pattern language
|
||||
* @note Inline visualizers are extensions to the [[hex::inline_visualize]] attribute, used to visualize data
|
||||
* @param name The name of the visualizer
|
||||
* @param func The function callback
|
||||
* @param parameterCount The amount of parameters the function takes
|
||||
*/
|
||||
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, u32 parameterCount);
|
||||
|
||||
}
|
||||
|
||||
/* View Registry. Allows adding of new windows */
|
||||
|
||||
@@ -23,7 +23,11 @@
|
||||
#define EVENT_DEF(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, true, __VA_ARGS__)
|
||||
#define EVENT_DEF_NO_LOG(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, false, __VA_ARGS__)
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
struct GLFWwindow;
|
||||
namespace hex { class Achievement; }
|
||||
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -39,7 +43,9 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool operator==(const EventId &rhs) const = default;
|
||||
constexpr bool operator==(const EventId &other) const {
|
||||
return this->m_hash == other.m_hash;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_hash;
|
||||
@@ -63,6 +69,9 @@ namespace hex {
|
||||
Callback m_func;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept EventType = std::derived_from<T, EventBase>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -80,9 +89,10 @@ namespace hex {
|
||||
* @param function Function to call when the event is posted
|
||||
* @return Token to unsubscribe from the event
|
||||
*/
|
||||
template<typename E>
|
||||
template<impl::EventType E>
|
||||
static EventList::iterator subscribe(typename E::Callback function) {
|
||||
return s_events.insert(s_events.end(), std::make_pair(E::Id, std::make_unique<E>(function)));
|
||||
auto &events = getEvents();
|
||||
return events.insert(events.end(), std::make_pair(E::Id, std::make_unique<E>(function)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,9 +101,9 @@ namespace hex {
|
||||
* @param token Unique token to register the event to. Later required to unsubscribe again
|
||||
* @param function Function to call when the event is posted
|
||||
*/
|
||||
template<typename E>
|
||||
template<impl::EventType E>
|
||||
static void subscribe(void *token, typename E::Callback function) {
|
||||
s_tokenStore.insert(std::make_pair(token, subscribe<E>(function)));
|
||||
getTokenStore().insert(std::make_pair(token, subscribe<E>(function)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +111,7 @@ namespace hex {
|
||||
* @param token Token returned by subscribe
|
||||
*/
|
||||
static void unsubscribe(const EventList::iterator &token) noexcept {
|
||||
s_events.erase(token);
|
||||
getEvents().erase(token);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,15 +119,16 @@ namespace hex {
|
||||
* @tparam E Event
|
||||
* @param token Token passed to subscribe
|
||||
*/
|
||||
template<typename E>
|
||||
template<impl::EventType E>
|
||||
static void unsubscribe(void *token) noexcept {
|
||||
auto iter = std::find_if(s_tokenStore.begin(), s_tokenStore.end(), [&](auto &item) {
|
||||
auto &tokenStore = getTokenStore();
|
||||
auto iter = std::find_if(tokenStore.begin(), tokenStore.end(), [&](auto &item) {
|
||||
return item.first == token && item.second->first == E::Id;
|
||||
});
|
||||
|
||||
if (iter != s_tokenStore.end()) {
|
||||
s_events.remove(*iter->second);
|
||||
s_tokenStore.erase(iter);
|
||||
if (iter != tokenStore.end()) {
|
||||
getEvents().remove(*iter->second);
|
||||
tokenStore.erase(iter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -127,9 +138,9 @@ namespace hex {
|
||||
* @tparam E Event
|
||||
* @param args Arguments to pass to the event
|
||||
*/
|
||||
template<typename E>
|
||||
template<impl::EventType E>
|
||||
static void post(auto &&...args) noexcept {
|
||||
for (const auto &[id, event] : s_events) {
|
||||
for (const auto &[id, event] : getEvents()) {
|
||||
if (id == E::Id) {
|
||||
(*static_cast<E *const>(event.get()))(std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
@@ -145,13 +156,13 @@ namespace hex {
|
||||
* @brief Unsubscribe all subscribers from all events
|
||||
*/
|
||||
static void clear() noexcept {
|
||||
s_events.clear();
|
||||
s_tokenStore.clear();
|
||||
getEvents().clear();
|
||||
getTokenStore().clear();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::map<void *, EventList::iterator> s_tokenStore;
|
||||
static EventList s_events;
|
||||
static std::map<void *, EventList::iterator>& getTokenStore();
|
||||
static EventList& getEvents();
|
||||
};
|
||||
|
||||
/* Default Events */
|
||||
@@ -195,11 +206,13 @@ namespace hex {
|
||||
EVENT_DEF(EventWindowInitialized);
|
||||
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
|
||||
EVENT_DEF(EventPatchCreated, u64, u8, u8);
|
||||
EVENT_DEF(EventPatternEvaluating);
|
||||
EVENT_DEF(EventPatternExecuted, const std::string&);
|
||||
EVENT_DEF(EventPatternEditorChanged, const std::string&);
|
||||
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
|
||||
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
|
||||
EVENT_DEF(EventImHexClosing);
|
||||
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
|
||||
|
||||
/**
|
||||
* @brief Called when a project has been loaded
|
||||
@@ -232,4 +245,16 @@ namespace hex {
|
||||
EVENT_DEF(RequestOpenInfoPopup, const std::string);
|
||||
EVENT_DEF(RequestOpenErrorPopup, const std::string);
|
||||
EVENT_DEF(RequestOpenFatalPopup, const std::string);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send an event to the main Imhex instance
|
||||
*/
|
||||
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
|
||||
|
||||
/**
|
||||
* Move the data from all PerProvider instances from one provider to another.
|
||||
* The 'from' provider should not have any per provider data after this, and should be immediately deleted
|
||||
*/
|
||||
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
|
||||
}
|
||||
@@ -261,6 +261,12 @@ namespace hex {
|
||||
*/
|
||||
void setCurrentProvider(u32 index);
|
||||
|
||||
/**
|
||||
* @brief Gets the index of the currently selected data provider
|
||||
* @return Index of the selected provider
|
||||
*/
|
||||
i64 getCurrentProviderIndex();
|
||||
|
||||
/**
|
||||
* @brief Checks whether the currently selected data provider is valid
|
||||
* @return Whether the currently selected data provider is valid
|
||||
@@ -322,7 +328,10 @@ namespace hex {
|
||||
/* Functions to interact with various ImHex system settings */
|
||||
namespace System {
|
||||
|
||||
bool isMainInstance();
|
||||
|
||||
namespace impl {
|
||||
void setMainInstanceStatus(bool status);
|
||||
|
||||
void setMainWindowPosition(i32 x, i32 y);
|
||||
void setMainWindowSize(u32 width, u32 height);
|
||||
@@ -331,8 +340,6 @@ namespace hex {
|
||||
void setGlobalScale(float scale);
|
||||
void setNativeScale(float scale);
|
||||
|
||||
void setProgramArguments(int argc, char **argv, char **envp);
|
||||
|
||||
void setBorderlessWindowMode(bool enabled);
|
||||
|
||||
void setCustomFontPath(const std::fs::path &path);
|
||||
@@ -383,20 +390,6 @@ namespace hex {
|
||||
void setTaskBarProgress(TaskProgressState state, TaskProgressType type, u32 progress);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the current program arguments
|
||||
* @return The current program arguments
|
||||
*/
|
||||
const ProgramArguments &getProgramArguments();
|
||||
|
||||
/**
|
||||
* @brief Gets a program argument
|
||||
* @param index The index of the argument to get
|
||||
* @return The argument at the given index
|
||||
*/
|
||||
std::optional<std::u8string> getProgramArgument(int index);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the current target FPS
|
||||
* @return The current target FPS
|
||||
@@ -460,7 +453,7 @@ namespace hex {
|
||||
* @brief Gets the current custom font path
|
||||
* @return The current custom font path
|
||||
*/
|
||||
const std::filesystem::path &getCustomFontPath();
|
||||
std::filesystem::path &getCustomFontPath();
|
||||
|
||||
/**
|
||||
* @brief Gets the current font size
|
||||
@@ -486,7 +479,7 @@ namespace hex {
|
||||
* @brief Gets the currently set additional folder paths
|
||||
* @return The currently set additional folder paths
|
||||
*/
|
||||
const std::vector<std::filesystem::path> &getAdditionalFolderPaths();
|
||||
std::vector<std::filesystem::path> &getAdditionalFolderPaths();
|
||||
|
||||
/**
|
||||
* @brief Sets the additional folder paths
|
||||
@@ -507,11 +500,62 @@ namespace hex {
|
||||
*/
|
||||
bool isPortableVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current Operating System name
|
||||
* @return Operating System name
|
||||
*/
|
||||
std::string getOSName();
|
||||
|
||||
/**
|
||||
* @brief Gets the current Operating System version
|
||||
* @return Operating System version
|
||||
*/
|
||||
std::string getOSVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current CPU architecture
|
||||
* @return CPU architecture
|
||||
*/
|
||||
std::string getArchitecture();
|
||||
|
||||
/**
|
||||
* @brief Gets the current ImHex version
|
||||
* @return ImHex version
|
||||
*/
|
||||
std::string getImHexVersion();
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit hash
|
||||
* @param longHash Whether to return the full hash or the shortened version
|
||||
* @return Git commit hash
|
||||
*/
|
||||
std::string getCommitHash(bool longHash = false);
|
||||
|
||||
/**
|
||||
* @brief Gets the current git commit branch
|
||||
* @return Git commit branch
|
||||
*/
|
||||
std::string getCommitBranch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cross-instance messaging system
|
||||
* This allows you to send messages to the "main" instance of ImHex running, from any other instance
|
||||
*/
|
||||
namespace Messaging {
|
||||
|
||||
namespace impl {
|
||||
using MessagingHandler = std::function<void(const std::vector<u8> &)>;
|
||||
|
||||
std::map<std::string, MessagingHandler> &getHandlers();
|
||||
|
||||
void runHandler(const std::string &eventName, const std::vector<u8> &args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register the handler for this specific event name
|
||||
*/
|
||||
void registerHandler(const std::string &eventName, const impl::MessagingHandler &handler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -413,9 +413,6 @@ namespace hex {
|
||||
* @brief Clear all shortcuts
|
||||
*/
|
||||
static void clearShortcuts();
|
||||
|
||||
private:
|
||||
static std::map<Shortcut, std::function<void()>> s_globalShortcuts;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -18,22 +18,48 @@ namespace hex {
|
||||
std::fs::path path;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Save the current layout
|
||||
* @param name Name of the layout
|
||||
*/
|
||||
static void save(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Load a layout from a file
|
||||
* @param path Path to the layout file
|
||||
*/
|
||||
static void load(const std::fs::path &path);
|
||||
|
||||
/**
|
||||
* @brief Load a layout from a string
|
||||
* @param content Layout string
|
||||
*/
|
||||
static void loadString(const std::string &content);
|
||||
|
||||
/**
|
||||
* @brief Get a list of all layouts
|
||||
* @return List of all added layouts
|
||||
*/
|
||||
static std::vector<Layout> getLayouts();
|
||||
|
||||
/**
|
||||
* @brief Handles loading of layouts if needed
|
||||
* @note This function should only be called by ImHex
|
||||
*/
|
||||
static void process();
|
||||
|
||||
/**
|
||||
* @brief Reload all layouts
|
||||
*/
|
||||
static void reload();
|
||||
|
||||
/**
|
||||
* @brief Reset the layout manager
|
||||
*/
|
||||
static void reset();
|
||||
|
||||
private:
|
||||
LayoutManager() = default;
|
||||
|
||||
static std::optional<std::fs::path> s_layoutPathToLoad;
|
||||
static std::optional<std::string> s_layoutStringToLoad;
|
||||
static std::vector<Layout> s_layouts;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -39,11 +39,10 @@ namespace hex {
|
||||
|
||||
static void resetLanguageStrings();
|
||||
|
||||
static const std::string &getSelectedLanguage();
|
||||
|
||||
private:
|
||||
std::string m_unlocalizedString;
|
||||
|
||||
static std::string s_fallbackLanguage;
|
||||
static std::map<std::string, std::string> s_currStrings;
|
||||
};
|
||||
|
||||
std::string operator+(const std::string &&left, const LangEntry &&right);
|
||||
@@ -64,6 +63,6 @@ template<>
|
||||
struct fmt::formatter<hex::LangEntry> : fmt::formatter<std::string_view> {
|
||||
template<typename FormatContext>
|
||||
auto format(const hex::LangEntry &entry, FormatContext &ctx) {
|
||||
return fmt::formatter<std::string_view>::format(entry, ctx);
|
||||
return fmt::formatter<std::string_view>::format(entry.get(), ctx);
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
@@ -17,6 +18,12 @@ struct ImGuiContext;
|
||||
|
||||
namespace hex {
|
||||
|
||||
struct SubCommand {
|
||||
std::string commandKey;
|
||||
std::string commandDesc;
|
||||
std::function<void(const std::vector<std::string>&)> callback;
|
||||
};
|
||||
|
||||
class Plugin {
|
||||
public:
|
||||
explicit Plugin(const std::fs::path &path);
|
||||
@@ -36,6 +43,8 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] bool isLoaded() const;
|
||||
|
||||
[[nodiscard]] std::span<SubCommand> getSubCommands() const;
|
||||
|
||||
private:
|
||||
using InitializePluginFunc = void (*)();
|
||||
using GetPluginNameFunc = const char *(*)();
|
||||
@@ -44,6 +53,7 @@ namespace hex {
|
||||
using GetCompatibleVersionFunc = const char *(*)();
|
||||
using SetImGuiContextFunc = void (*)(ImGuiContext *);
|
||||
using IsBuiltinPluginFunc = bool (*)();
|
||||
using GetSubCommandsFunc = void* (*)();
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
HMODULE m_handle = nullptr;
|
||||
@@ -61,6 +71,7 @@ namespace hex {
|
||||
GetCompatibleVersionFunc m_getCompatibleVersionFunction = nullptr;
|
||||
SetImGuiContextFunc m_setImGuiContextFunction = nullptr;
|
||||
IsBuiltinPluginFunc m_isBuiltinPluginFunction = nullptr;
|
||||
GetSubCommandsFunc m_getSubCommandsFunction = nullptr;
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] auto getPluginFunction(const std::string &symbol) {
|
||||
@@ -79,13 +90,7 @@ namespace hex {
|
||||
static void unload();
|
||||
static void reload();
|
||||
|
||||
static const auto &getPlugins() {
|
||||
return PluginManager::s_plugins;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::fs::path s_pluginFolder;
|
||||
static std::vector<Plugin> s_plugins;
|
||||
static const std::vector<Plugin> &getPlugins();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -47,7 +47,7 @@ namespace hex {
|
||||
*/
|
||||
static void setProjectFunctions(
|
||||
const std::function<bool(const std::fs::path&)> &loadFun,
|
||||
const std::function<bool(std::optional<std::fs::path>)> &storeFun
|
||||
const std::function<bool(std::optional<std::fs::path>, bool)> &storeFun
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -63,10 +63,11 @@ namespace hex {
|
||||
* @brief Store a project file
|
||||
*
|
||||
* @param filePath Path to the project file
|
||||
* @param updateLocation update the project location so subssequent saves will save there
|
||||
* @return true if the project file was stored successfully
|
||||
* @return false if the project file was not stored successfully
|
||||
*/
|
||||
static bool store(std::optional<std::fs::path> filePath = std::nullopt);
|
||||
static bool store(std::optional<std::fs::path> filePath = std::nullopt, bool updateLocation = true);
|
||||
|
||||
/**
|
||||
* @brief Check if a project file is currently loaded
|
||||
@@ -115,27 +116,16 @@ namespace hex {
|
||||
* @brief Get the list of registered handlers
|
||||
* @return List of registered handlers
|
||||
*/
|
||||
static std::vector<Handler>& getHandlers() {
|
||||
return s_handlers;
|
||||
}
|
||||
static std::vector<Handler>& getHandlers();
|
||||
|
||||
/**
|
||||
* @brief Get the list of registered per-provider handlers
|
||||
* @return List of registered per-provider handlers
|
||||
*/
|
||||
static std::vector<ProviderHandler>& getProviderHandlers() {
|
||||
return s_providerHandlers;
|
||||
}
|
||||
static std::vector<ProviderHandler>& getProviderHandlers();
|
||||
|
||||
private:
|
||||
ProjectFile() = default;
|
||||
|
||||
static std::function<bool(const std::fs::path&)> s_loadProjectFunction;
|
||||
static std::function<bool(std::optional<std::fs::path>)> s_storeProjectFunction;
|
||||
|
||||
static std::fs::path s_currProjectPath;
|
||||
static std::vector<Handler> s_handlers;
|
||||
static std::vector<ProviderHandler> s_providerHandlers;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -115,6 +115,11 @@ namespace hex {
|
||||
std::weak_ptr<Task> m_task;
|
||||
};
|
||||
|
||||
struct Timer {
|
||||
std::chrono::time_point<std::chrono::steady_clock> elapseTime;
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The Task Manager is responsible for running and managing asynchronous tasks
|
||||
*/
|
||||
@@ -144,7 +149,6 @@ namespace hex {
|
||||
*/
|
||||
static TaskHolder createBackgroundTask(std::string name, std::function<void(Task &)> function);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame
|
||||
* @param function Function to be executed
|
||||
@@ -157,6 +161,12 @@ namespace hex {
|
||||
*/
|
||||
static void runWhenTasksFinished(const std::function<void()> &function);
|
||||
|
||||
/**
|
||||
* @brief Creates a callback that will be executed after the given time
|
||||
* @param duration Time to wait
|
||||
* @param function Function to be executed
|
||||
*/
|
||||
static void doAfter(std::chrono::duration<i64> duration, const std::function<void()> &function);
|
||||
|
||||
static void collectGarbage();
|
||||
|
||||
@@ -164,20 +174,10 @@ namespace hex {
|
||||
static size_t getRunningBackgroundTaskCount();
|
||||
|
||||
static std::list<std::shared_ptr<Task>> &getRunningTasks();
|
||||
static std::list<Timer> &getTimers();
|
||||
static void runDeferredCalls();
|
||||
|
||||
private:
|
||||
static std::mutex s_deferredCallsMutex, s_tasksFinishedMutex;
|
||||
|
||||
static std::list<std::shared_ptr<Task>> s_tasks;
|
||||
static std::list<std::shared_ptr<Task>> s_taskQueue;
|
||||
static std::list<std::function<void()>> s_deferredCalls;
|
||||
static std::list<std::function<void()>> s_tasksFinishedCallbacks;
|
||||
|
||||
static std::mutex s_queueMutex;
|
||||
static std::condition_variable s_jobCondVar;
|
||||
static std::vector<std::jthread> s_workers;
|
||||
|
||||
static void runner(const std::stop_token &stopToken);
|
||||
};
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace hex {
|
||||
|
||||
|
||||
static std::vector<std::string> getThemeNames();
|
||||
static const std::string &getThemeImagePostfix();
|
||||
static const std::string &getImageTheme();
|
||||
|
||||
static std::optional<ImColor> parseColorString(const std::string &colorString);
|
||||
|
||||
@@ -78,18 +78,11 @@ namespace hex {
|
||||
StyleMap styleMap;
|
||||
};
|
||||
|
||||
static std::map<std::string, ThemeHandler>& getThemeHandlers() { return s_themeHandlers; }
|
||||
static std::map<std::string, StyleHandler>& getStyleHandlers() { return s_styleHandlers; }
|
||||
static std::map<std::string, ThemeHandler>& getThemeHandlers();
|
||||
static std::map<std::string, StyleHandler>& getStyleHandlers();
|
||||
|
||||
private:
|
||||
ThemeManager() = default;
|
||||
|
||||
|
||||
static std::map<std::string, nlohmann::json> s_themes;
|
||||
static std::map<std::string, ThemeHandler> s_themeHandlers;
|
||||
static std::map<std::string, StyleHandler> s_styleHandlers;
|
||||
static std::string s_imagePostfix;
|
||||
static std::string s_currTheme;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -51,10 +51,7 @@ namespace hex::dp {
|
||||
|
||||
[[nodiscard]] std::vector<u8>& getDefaultData() { return this->m_defaultData; }
|
||||
|
||||
static void setIdCounter(int id) {
|
||||
if (id > Attribute::s_idCounter)
|
||||
Attribute::s_idCounter = id;
|
||||
}
|
||||
static void setIdCounter(int id);
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
@@ -69,8 +66,6 @@ namespace hex::dp {
|
||||
|
||||
friend class Node;
|
||||
void setParentNode(Node *node) { this->m_parentNode = node; }
|
||||
|
||||
static int s_idCounter;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -14,16 +14,11 @@ namespace hex::dp {
|
||||
[[nodiscard]] int getFromId() const { return this->m_from; }
|
||||
[[nodiscard]] int getToId() const { return this->m_to; }
|
||||
|
||||
static void setIdCounter(int id) {
|
||||
if (id > Link::s_idCounter)
|
||||
Link::s_idCounter = id;
|
||||
}
|
||||
static void setIdCounter(int id);
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
int m_from, m_to;
|
||||
|
||||
static int s_idCounter;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -69,18 +69,15 @@ namespace hex::dp {
|
||||
return this->m_position;
|
||||
}
|
||||
|
||||
static void setIdCounter(int id) {
|
||||
if (id > Node::s_idCounter)
|
||||
Node::s_idCounter = id;
|
||||
}
|
||||
static void setIdCounter(int id);
|
||||
|
||||
const std::vector<u8>& getBufferOnInput(u32 index);
|
||||
const i128& getIntegerOnInput(u32 index);
|
||||
const long double& getFloatOnInput(u32 index);
|
||||
const double& getFloatOnInput(u32 index);
|
||||
|
||||
void setBufferOnOutput(u32 index, std::span<const u8> data);
|
||||
void setIntegerOnOutput(u32 index, i128 integer);
|
||||
void setFloatOnOutput(u32 index, long double floatingPoint);
|
||||
void setFloatOnOutput(u32 index, double floatingPoint);
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
@@ -90,8 +87,6 @@ namespace hex::dp {
|
||||
prv::Overlay *m_overlay = nullptr;
|
||||
ImVec2 m_position;
|
||||
|
||||
static int s_idCounter;
|
||||
|
||||
Attribute& getAttribute(u32 index) {
|
||||
if (index >= this->getAttributes().size())
|
||||
throw std::runtime_error("Attribute index out of bounds!");
|
||||
|
||||
@@ -26,9 +26,11 @@ namespace hex {
|
||||
RISCV = CS_ARCH_RISCV,
|
||||
MOS65XX = CS_ARCH_MOS65XX,
|
||||
BPF = CS_ARCH_BPF,
|
||||
SH = CS_ARCH_SH,
|
||||
TRICORE = CS_ARCH_TRICORE,
|
||||
#endif
|
||||
|
||||
MAX = CS_ARCH_MAX,
|
||||
MAX = TRICORE,
|
||||
MIN = ARM
|
||||
};
|
||||
|
||||
@@ -43,7 +45,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
constexpr static auto ArchitectureNames = [](){
|
||||
std::array<const char *, static_cast<u32>(Architecture::MAX)> names = { };
|
||||
std::array<const char *, static_cast<u32>(Architecture::MAX) + 1> names = { };
|
||||
|
||||
names[CS_ARCH_ARM] = "ARM";
|
||||
names[CS_ARCH_ARM64] = "AArch64";
|
||||
@@ -63,6 +65,8 @@ namespace hex {
|
||||
names[CS_ARCH_RISCV] = "RISC-V";
|
||||
names[CS_ARCH_MOS65XX] = "MOS Technology 65xx";
|
||||
names[CS_ARCH_BPF] = "Berkeley Packet Filter";
|
||||
names[CS_ARCH_SH] = "SuperH";
|
||||
names[CS_ARCH_TRICORE] = "Tricore";
|
||||
#endif
|
||||
|
||||
return names;
|
||||
@@ -75,7 +79,7 @@ namespace hex {
|
||||
return supportedCount;
|
||||
}
|
||||
|
||||
for (supportedCount = static_cast<i32>(Architecture::MIN); supportedCount < static_cast<i32>(Architecture::MAX); supportedCount++) {
|
||||
for (supportedCount = static_cast<i32>(Architecture::MIN); supportedCount < static_cast<i32>(Architecture::MAX) + 1; supportedCount++) {
|
||||
if (!cs_support(supportedCount)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -37,11 +37,14 @@ namespace hex {
|
||||
|
||||
[[nodiscard]] const std::string& getTableContent() const { return this->m_tableContent; }
|
||||
|
||||
[[nodiscard]] const std::string& getName() const { return this->m_name; }
|
||||
|
||||
private:
|
||||
void parse(const std::string &content);
|
||||
|
||||
bool m_valid = false;
|
||||
|
||||
std::string m_name;
|
||||
std::string m_tableContent;
|
||||
std::unique_ptr<std::map<size_t, std::map<std::vector<u8>, std::string>>> m_mapping;
|
||||
size_t m_longestSequence = 0;
|
||||
|
||||
@@ -16,4 +16,10 @@ namespace hex {
|
||||
fmt::print(fmt::runtime(format), args...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void println(std::string_view format, Args... args) {
|
||||
fmt::print(fmt::runtime(format), args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -75,8 +75,6 @@ namespace hex {
|
||||
this->m_url = std::move(other.m_url);
|
||||
this->m_headers = std::move(other.m_headers);
|
||||
this->m_body = std::move(other.m_body);
|
||||
|
||||
this->m_caCert = std::move(other.m_caCert);
|
||||
}
|
||||
|
||||
HttpRequest& operator=(HttpRequest &&other) noexcept {
|
||||
@@ -88,18 +86,10 @@ namespace hex {
|
||||
this->m_headers = std::move(other.m_headers);
|
||||
this->m_body = std::move(other.m_body);
|
||||
|
||||
this->m_caCert = std::move(other.m_caCert);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
static void setCACert(std::string data) {
|
||||
HttpRequest::s_caCertData = std::move(data);
|
||||
}
|
||||
|
||||
static void setProxy(std::string proxy) {
|
||||
HttpRequest::s_proxyUrl = std::move(proxy);
|
||||
}
|
||||
static void setProxy(std::string proxy);
|
||||
|
||||
void setMethod(std::string method) {
|
||||
this->m_method = std::move(method);
|
||||
@@ -286,9 +276,7 @@ namespace hex {
|
||||
char *url = nullptr;
|
||||
curl_easy_getinfo(this->m_curl, CURLINFO_EFFECTIVE_URL, &url);
|
||||
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", this->m_method, url, u32(result), curl_easy_strerror(result));
|
||||
if (!HttpRequest::s_proxyUrl.empty()){
|
||||
log::info("A custom proxy '{0}' is in use. Is it working correctly?", HttpRequest::s_proxyUrl);
|
||||
}
|
||||
checkProxyErrors();
|
||||
|
||||
return { };
|
||||
}
|
||||
@@ -300,11 +288,13 @@ namespace hex {
|
||||
return Result<T>(statusCode, { data.begin(), data.end() });
|
||||
}
|
||||
|
||||
[[maybe_unused]] static CURLcode sslCtxFunction(CURL *ctx, void *sslctx, void *userData);
|
||||
static size_t writeToVector(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||
static size_t writeToFile(void *contents, size_t size, size_t nmemb, void *userdata);
|
||||
static int progressCallback(void *contents, curl_off_t dlTotal, curl_off_t dlNow, curl_off_t ulTotal, curl_off_t ulNow);
|
||||
|
||||
private:
|
||||
static void checkProxyErrors();
|
||||
|
||||
private:
|
||||
CURL *m_curl;
|
||||
|
||||
@@ -318,9 +308,6 @@ namespace hex {
|
||||
|
||||
std::atomic<float> m_progress = 0.0F;
|
||||
std::atomic<bool> m_canceled = false;
|
||||
|
||||
[[maybe_unused]] std::unique_ptr<mbedtls_x509_crt> m_caCert;
|
||||
static std::string s_caCertData, s_proxyUrl;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -20,12 +20,20 @@ namespace hex::log {
|
||||
bool isRedirected();
|
||||
[[maybe_unused]] void redirectToFile();
|
||||
|
||||
extern std::mutex s_loggerMutex;
|
||||
extern std::mutex g_loggerMutex;
|
||||
|
||||
struct LogEntry {
|
||||
std::string project;
|
||||
std::string level;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
std::vector<LogEntry>& getLogEntries();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
[[maybe_unused]] void printPrefix(FILE *dest, const fmt::text_style &ts, const std::string &level) {
|
||||
const auto now = fmt::localtime(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
|
||||
|
||||
@@ -37,26 +45,33 @@ namespace hex::log {
|
||||
fmt::print(dest, ts, "{0} ", level);
|
||||
|
||||
fmt::print(dest, "[{0}] ", IMHEX_PROJECT_NAME);
|
||||
|
||||
constexpr static auto ProjectNameLength = std::char_traits<char>::length(IMHEX_PROJECT_NAME);
|
||||
fmt::print(dest, "{}", std::string(ProjectNameLength > 10 ? 0 : 10 - ProjectNameLength, ' '));
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
[[maybe_unused]] void print(const fmt::text_style &ts, const std::string &level, const std::string &fmt, auto... args) {
|
||||
std::scoped_lock lock(impl::s_loggerMutex);
|
||||
std::scoped_lock lock(impl::g_loggerMutex);
|
||||
|
||||
auto dest = impl::getDestination();
|
||||
printPrefix(dest, ts, level);
|
||||
fmt::print(dest, fmt::runtime(fmt), args...);
|
||||
fmt::print(dest, "\n");
|
||||
|
||||
auto message = fmt::format(fmt::runtime(fmt), args...);
|
||||
fmt::print(dest, "{}\n", message);
|
||||
fflush(dest);
|
||||
|
||||
impl::getLogEntries().push_back({ IMHEX_PROJECT_NAME, level, std::move(message) });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[[maybe_unused]] void debug(const std::string &fmt, auto &&...args) {
|
||||
#if defined(DEBUG)
|
||||
hex::log::print(fg(fmt::color::light_green) | fmt::emphasis::bold, "[DEBUG]", fmt, args...);
|
||||
#else
|
||||
hex::unused(fmt, args...);
|
||||
#endif
|
||||
#if defined(DEBUG)
|
||||
hex::log::print(fg(fmt::color::light_green) | fmt::emphasis::bold, "[DEBUG]", fmt, args...);
|
||||
#else
|
||||
impl::getLogEntries().push_back({ IMHEX_PROJECT_NAME, "[DEBUG]", fmt::format(fmt::runtime(fmt), args...) });
|
||||
#endif
|
||||
}
|
||||
|
||||
[[maybe_unused]] void info(const std::string &fmt, auto &&...args) {
|
||||
|
||||
9
lib/libimhex/include/hex/helpers/utils_linux.hpp
Normal file
9
lib/libimhex/include/hex/helpers/utils_linux.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
namespace hex {
|
||||
void executeCmd(const std::vector<std::string> &argsVector);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/api/plugin_manager.hpp>
|
||||
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
/**
|
||||
* This macro is used to define all the required entry points for a plugin.
|
||||
@@ -21,3 +26,20 @@
|
||||
GImGui = ctx; \
|
||||
} \
|
||||
extern "C" [[gnu::visibility("default")]] void initializePlugin()
|
||||
|
||||
/**
|
||||
* This macro is used to define subcommands defined by the plugin
|
||||
* A subcommand consists of a key, a description, and a callback
|
||||
* The key is what the first argument to ImHex should be, prefixed by `--`
|
||||
* For example, if the key if `help`, ImHex should be started with `--help` as its first argument to trigger the subcommand
|
||||
* when the subcommand is triggerred, it's callback will be executed. The callback is executed BEFORE most of ImHex initialization
|
||||
* so to do anything meaningful, you should subscribe to an event (like EventImHexStartupFinished) and run your code there.
|
||||
*/
|
||||
#define IMHEX_PLUGIN_SUBCOMMANDS() IMHEX_PLUGIN_SUBCOMMANDS_IMPL()
|
||||
|
||||
#define IMHEX_PLUGIN_SUBCOMMANDS_IMPL() \
|
||||
extern std::vector<hex::SubCommand> g_subCommands; \
|
||||
extern "C" [[gnu::visibility("default")]] void* getSubCommands() { \
|
||||
return &g_subCommands; \
|
||||
} \
|
||||
std::vector<hex::SubCommand> g_subCommands
|
||||
|
||||
@@ -36,11 +36,68 @@ namespace hex::prv {
|
||||
Provider();
|
||||
virtual ~Provider();
|
||||
|
||||
/**
|
||||
* @brief Opens this provider
|
||||
* @note The return value of this function allows to ensure the provider is available,
|
||||
* so calling Provider::isAvailable() just after a call to open() that returned true is redundant.
|
||||
* @note This is not related to the EventProviderOpened event
|
||||
* @return true if the provider was opened successfully, else false
|
||||
*/
|
||||
[[nodiscard]] virtual bool open() = 0;
|
||||
|
||||
/**
|
||||
* @brief Closes this provider
|
||||
* @note This function is called when the user requests for a provider to be closed, e.g. by closing a tab.
|
||||
* In general, this function should close the underlying data source but leave the provider in a state where
|
||||
* it can be opened again later by calling the open() function again.
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* @brief Checks if this provider is open and can be used to access data
|
||||
* @return Generally, if the open() function succeeded and the data source was successfully opened, this
|
||||
* function should return true
|
||||
*/
|
||||
[[nodiscard]] virtual bool isAvailable() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Checks if the data in this provider can be read
|
||||
* @return True if the provider is readable, false otherwise
|
||||
*/
|
||||
[[nodiscard]] virtual bool isReadable() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Controls if the user can write data to this specific provider.
|
||||
* This may be false for e.g. a file opened in read-only
|
||||
*/
|
||||
[[nodiscard]] virtual bool isWritable() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Controls if the user can resize this provider
|
||||
* @return True if the provider is resizable, false otherwise
|
||||
*/
|
||||
[[nodiscard]] virtual bool isResizable() const = 0;
|
||||
[[nodiscard]] virtual bool isSavable() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Controls whether the provider can be saved ("saved", not "saved as")
|
||||
* This is mainly used by providers that aren't buffered, and so don't need to be saved
|
||||
* This function will usually return false for providers that aren't writable, but this isn't guaranted
|
||||
*/
|
||||
[[nodiscard]] virtual bool isSavable() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Controls whether we can dump data from this provider (e.g. "save as", or "export -> ..").
|
||||
* Typically disabled for process with sparse data, like the Process memory provider
|
||||
* where the virtual address space is several TiBs large.
|
||||
* Default implementation returns true.
|
||||
*/
|
||||
[[nodiscard]] virtual bool isDumpable() const;
|
||||
|
||||
/**
|
||||
* @brief Controls whether this provider can be saved as a recent entry
|
||||
* Typically used for providers that do not retain data, e.g. the memory provider
|
||||
*/
|
||||
[[nodiscard]] virtual bool isSavableAsRecent() const { return true; }
|
||||
|
||||
/**
|
||||
* @brief Read data from this provider, applying overlays and patches
|
||||
@@ -59,20 +116,13 @@ namespace hex::prv {
|
||||
*/
|
||||
virtual void write(u64 offset, const void *buffer, size_t size);
|
||||
|
||||
virtual void resize(size_t newSize);
|
||||
virtual void insert(u64 offset, size_t size);
|
||||
virtual void remove(u64 offset, size_t size);
|
||||
|
||||
virtual void save();
|
||||
virtual void saveAs(const std::fs::path &path);
|
||||
|
||||
/**
|
||||
* @brief Read data from this provider, without applying overlays and patches
|
||||
* @param offset offset to start reading the data
|
||||
* @param buffer buffer to write read data
|
||||
* @param size number of bytes to read
|
||||
*/
|
||||
virtual void readRaw(u64 offset, void *buffer, size_t size) = 0;
|
||||
virtual void readRaw(u64 offset, void *buffer, size_t size) = 0;
|
||||
/**
|
||||
* @brief Write data directly to this provider
|
||||
* @param offset offset to start writing the data
|
||||
@@ -80,7 +130,39 @@ namespace hex::prv {
|
||||
* @param size number of bytes to write
|
||||
*/
|
||||
virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0;
|
||||
[[nodiscard]] virtual size_t getActualSize() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the full size of the data in this provider
|
||||
* @return The size of the entire available data of this provider
|
||||
*/
|
||||
[[nodiscard]] virtual size_t getActualSize() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets the type name of this provider
|
||||
* @note This is mainly used to be stored in project files and recents to be able to later on
|
||||
* recreate this exact provider type. This needs to be unique across all providers, this is usually something
|
||||
* like "hex.builtin.provider.memory" or "hex.builtin.provider.file"
|
||||
* @return The provider's type name
|
||||
*/
|
||||
[[nodiscard]] virtual std::string getTypeName() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Gets a human readable representation of the current provider
|
||||
* @note This is mainly used to display the provider in the UI. For example, the file provider
|
||||
* will return the file name here
|
||||
* @return The name of the current provider
|
||||
*/
|
||||
[[nodiscard]] virtual std::string getName() const = 0;
|
||||
|
||||
|
||||
|
||||
virtual void resize(size_t newSize);
|
||||
virtual void insert(u64 offset, size_t size);
|
||||
virtual void remove(u64 offset, size_t size);
|
||||
|
||||
virtual void save();
|
||||
virtual void saveAs(const std::fs::path &path);
|
||||
|
||||
|
||||
void applyOverlays(u64 offset, void *buffer, size_t size);
|
||||
|
||||
@@ -90,7 +172,7 @@ namespace hex::prv {
|
||||
|
||||
[[nodiscard]] Overlay *newOverlay();
|
||||
void deleteOverlay(Overlay *overlay);
|
||||
[[nodiscard]] const std::list<Overlay *> &getOverlays();
|
||||
[[nodiscard]] const std::list<std::unique_ptr<Overlay>> &getOverlays();
|
||||
|
||||
[[nodiscard]] size_t getPageSize() const;
|
||||
void setPageSize(size_t pageSize);
|
||||
@@ -105,20 +187,9 @@ namespace hex::prv {
|
||||
[[nodiscard]] virtual size_t getSize() const;
|
||||
[[nodiscard]] virtual std::optional<u32> getPageOfAddress(u64 address) const;
|
||||
|
||||
[[nodiscard]] virtual std::string getName() const = 0;
|
||||
[[nodiscard]] virtual std::vector<Description> getDataDescription() const = 0;
|
||||
[[nodiscard]] virtual std::vector<Description> getDataDescription() const;
|
||||
[[nodiscard]] virtual std::variant<std::string, i128> queryInformation(const std::string &category, const std::string &argument);
|
||||
|
||||
/**
|
||||
* @brief Opens this provider
|
||||
* the return value of this function allows to ensure the provider is available,
|
||||
* so calling Provider::isAvailable() just after a call to open() that returned true is dedundant.
|
||||
* @note This is not related to the EventProviderOpened event
|
||||
* @return true if the provider was opened sucessfully, else false
|
||||
*/
|
||||
[[nodiscard]] virtual bool open() = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
void addPatch(u64 offset, const void *buffer, size_t size, bool createUndo = false);
|
||||
void createUndoPoint();
|
||||
|
||||
@@ -131,9 +202,7 @@ namespace hex::prv {
|
||||
[[nodiscard]] virtual bool hasFilePicker() const;
|
||||
virtual bool handleFilePicker();
|
||||
|
||||
virtual std::vector<MenuEntry> getMenuEntries() {
|
||||
return { };
|
||||
};
|
||||
virtual std::vector<MenuEntry> getMenuEntries() { return { }; }
|
||||
|
||||
[[nodiscard]] virtual bool hasLoadInterface() const;
|
||||
[[nodiscard]] virtual bool hasInterface() const;
|
||||
@@ -146,8 +215,6 @@ namespace hex::prv {
|
||||
[[nodiscard]] virtual nlohmann::json storeSettings(nlohmann::json settings = { }) const;
|
||||
virtual void loadSettings(const nlohmann::json &settings);
|
||||
|
||||
[[nodiscard]] virtual std::string getTypeName() const = 0;
|
||||
|
||||
void markDirty(bool dirty = true) { this->m_dirty = dirty; }
|
||||
[[nodiscard]] bool isDirty() const { return this->m_dirty; }
|
||||
|
||||
@@ -165,7 +232,7 @@ namespace hex::prv {
|
||||
|
||||
std::list<std::map<u64, u8>> m_patches;
|
||||
decltype(m_patches)::iterator m_currPatches;
|
||||
std::list<Overlay *> m_overlays;
|
||||
std::list<std::unique_ptr<Overlay>> m_overlays;
|
||||
|
||||
u32 m_id;
|
||||
|
||||
@@ -187,9 +254,6 @@ namespace hex::prv {
|
||||
std::string m_errorMessage;
|
||||
|
||||
size_t m_pageSize = MaxPageSize;
|
||||
|
||||
private:
|
||||
static u32 s_idCounter;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -82,6 +82,22 @@ namespace hex {
|
||||
EventManager::subscribe<EventImHexClosing>(this, [this] {
|
||||
this->m_data.clear();
|
||||
});
|
||||
|
||||
// moves the data of this PerProvider instance from one provider to another
|
||||
EventManager::subscribe<MovePerProviderData>(this, [this](prv::Provider *from, prv::Provider *to) {
|
||||
// get the value from the old provider, (removes it from the map)
|
||||
auto node = m_data.extract(from);
|
||||
|
||||
// ensure the value existed
|
||||
if (node.empty()) return;
|
||||
|
||||
// delete the value from the new provider, that we want to replace
|
||||
this->m_data.erase(to);
|
||||
|
||||
// re-insert it with the key of the new provider
|
||||
node.key() = to;
|
||||
this->m_data.insert(std::move(node));
|
||||
});
|
||||
}
|
||||
|
||||
void onDestroy() {
|
||||
|
||||
30
lib/libimhex/include/hex/subcommands/subcommands.hpp
Normal file
30
lib/libimhex/include/hex/subcommands/subcommands.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include<vector>
|
||||
#include<string>
|
||||
#include<functional>
|
||||
|
||||
namespace hex::subcommands {
|
||||
/**
|
||||
* @brief Internal method - takes all the arguments ImHex received from the command line,
|
||||
* and determine which subcommands to run, with which arguments.
|
||||
* In some cases, the subcommand or this function directly might exit the program
|
||||
* (e.g. --help, or when forwarding providers to open to another instance)
|
||||
* and so this function might not return
|
||||
*/
|
||||
void processArguments(const std::vector<std::string> &args);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Forward the given command to the main instance (might be this instance)
|
||||
* The callback will be executed after EventImHexStartupFinished
|
||||
*/
|
||||
void forwardSubCommand(const std::string &cmdName, const std::vector<std::string> &args);
|
||||
|
||||
using ForwardCommandHandler = std::function<void(const std::vector<std::string> &)>;
|
||||
|
||||
/**
|
||||
* @brief Register the handler for this specific command name
|
||||
*/
|
||||
void registerSubCommand(const std::string &cmdName, const ForwardCommandHandler &handler);
|
||||
}
|
||||
@@ -2,14 +2,18 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <span>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
enum ImGuiCustomCol {
|
||||
ImGuiCustomCol_DescButton,
|
||||
ImGuiCustomCol_DescButtonHovered,
|
||||
@@ -46,6 +50,7 @@ namespace ImGui {
|
||||
public:
|
||||
Texture() = default;
|
||||
Texture(const ImU8 *buffer, int size, int width = 0, int height = 0);
|
||||
Texture(std::span<const std::byte> bytes, int width = 0, int height = 0);
|
||||
explicit Texture(const char *path);
|
||||
Texture(unsigned int texture, int width, int height);
|
||||
Texture(const Texture&) = delete;
|
||||
@@ -141,6 +146,24 @@ namespace ImGui {
|
||||
ImGui::TextUnformatted(hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
|
||||
inline void TextFormattedSelectable(const std::string &fmt, auto &&...args) {
|
||||
auto text = hex::format(fmt, std::forward<decltype(args)>(args)...);
|
||||
|
||||
ImGui::PushID(text.c_str());
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(-FLT_MIN);
|
||||
ImGui::InputText("##", const_cast<char *>(text.c_str()), text.size(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
inline void TextFormattedColored(ImColor color, const std::string &fmt, auto &&...args) {
|
||||
ImGui::TextColored(color, "%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
@@ -153,6 +176,35 @@ namespace ImGui {
|
||||
ImGui::TextWrapped("%s", hex::format(fmt, std::forward<decltype(args)>(args)...).c_str());
|
||||
}
|
||||
|
||||
inline void TextFormattedWrappedSelectable(const std::string &fmt, auto &&...args) {
|
||||
//Manually wrap text, using the letter M (generally the widest character in non-monospaced fonts) to calculate the character width to use.
|
||||
auto text = wolv::util::wrapMonospacedString(
|
||||
hex::format(fmt, std::forward<decltype(args)>(args)...),
|
||||
ImGui::CalcTextSize("M").x,
|
||||
ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ScrollbarSize - ImGui::GetStyle().FrameBorderSize
|
||||
);
|
||||
|
||||
ImGui::PushID(text.c_str());
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4());
|
||||
|
||||
ImGui::PushItemWidth(-FLT_MIN);
|
||||
ImGui::InputTextMultiline(
|
||||
"##",
|
||||
const_cast<char *>(text.c_str()),
|
||||
text.size(),
|
||||
ImVec2(0, -FLT_MIN),
|
||||
ImGuiInputTextFlags_ReadOnly | ImGuiInputTextFlags_NoHorizontalScroll
|
||||
);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
inline void TextFormattedCentered(const std::string &fmt, auto &&...args) {
|
||||
auto text = hex::format(fmt, std::forward<decltype(args)>(args)...);
|
||||
auto availableSpace = ImGui::GetContentRegionAvail();
|
||||
@@ -165,6 +217,18 @@ namespace ImGui {
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
||||
inline void TextFormattedCenteredHorizontal(const std::string &fmt, auto &&...args) {
|
||||
auto text = hex::format(fmt, std::forward<decltype(args)>(args)...);
|
||||
auto availableSpace = ImGui::GetContentRegionAvail();
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str(), nullptr, false, availableSpace.x * 0.75F);
|
||||
|
||||
ImGui::SetCursorPosX(((availableSpace - textSize) / 2.0F).x);
|
||||
|
||||
ImGui::PushTextWrapPos(availableSpace.x * 0.75F);
|
||||
ImGui::TextFormattedWrapped("{}", text);
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
|
||||
bool InputText(const char* label, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputTextIcon(const char* label, const char *icon, std::string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
bool InputText(const char *label, std::u8string &buffer, ImGuiInputTextFlags flags = ImGuiInputTextFlags_None);
|
||||
@@ -179,5 +243,7 @@ namespace ImGui {
|
||||
|
||||
bool DimmedButton(const char* label);
|
||||
bool DimmedIconButton(const char *symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
bool DimmedIconToggle(const char *icon, bool *v);
|
||||
|
||||
void TextOverlay(const char *text, ImVec2 pos);
|
||||
}
|
||||
@@ -34,9 +34,7 @@ namespace hex {
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::vector<std::unique_ptr<PopupBase>> &getOpenPopups() {
|
||||
return s_openPopups;
|
||||
}
|
||||
[[nodiscard]] static std::vector<std::unique_ptr<PopupBase>> &getOpenPopups();
|
||||
|
||||
[[nodiscard]] const std::string &getUnlocalizedName() const {
|
||||
return this->m_unlocalizedName;
|
||||
@@ -58,9 +56,6 @@ namespace hex {
|
||||
return this->m_close;
|
||||
}
|
||||
|
||||
protected:
|
||||
static std::vector<std::unique_ptr<PopupBase>> s_openPopups;
|
||||
|
||||
private:
|
||||
|
||||
std::string m_unlocalizedName;
|
||||
@@ -84,7 +79,7 @@ namespace hex {
|
||||
|
||||
auto popup = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
|
||||
s_openPopups.emplace_back(std::move(popup));
|
||||
getOpenPopups().emplace_back(std::move(popup));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -51,20 +51,17 @@ namespace hex {
|
||||
return LangEntry(unlocalizedName) + "###" + unlocalizedName;
|
||||
}
|
||||
|
||||
static ImFontAtlas *getFontAtlas() { return View::s_fontAtlas; }
|
||||
static void setFontAtlas(ImFontAtlas *atlas) { View::s_fontAtlas = atlas; }
|
||||
static ImFontAtlas *getFontAtlas();
|
||||
static void setFontAtlas(ImFontAtlas *atlas);
|
||||
|
||||
static ImFontConfig getFontConfig() { return View::s_fontConfig; }
|
||||
static void setFontConfig(ImFontConfig config) { View::s_fontConfig = config; }
|
||||
static ImFontConfig getFontConfig();
|
||||
static void setFontConfig(ImFontConfig config);
|
||||
|
||||
private:
|
||||
std::string m_unlocalizedViewName;
|
||||
bool m_windowOpen = false;
|
||||
std::map<Shortcut, std::function<void()>> m_shortcuts;
|
||||
|
||||
static ImFontAtlas *s_fontAtlas;
|
||||
static ImFontConfig s_fontConfig;
|
||||
|
||||
friend class ShortcutManager;
|
||||
};
|
||||
|
||||
|
||||
223
lib/libimhex/source/api/achievement_manager.cpp
Normal file
223
lib/libimhex/source/api/achievement_manager.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>> &AchievementManager::getAchievements() {
|
||||
static std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>> achievements;
|
||||
|
||||
return achievements;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::list<AchievementManager::AchievementNode>>& AchievementManager::getAchievementNodes(bool rebuild) {
|
||||
static std::unordered_map<std::string, std::list<AchievementNode>> nodeCategoryStorage;
|
||||
|
||||
if (!nodeCategoryStorage.empty() || !rebuild)
|
||||
return nodeCategoryStorage;
|
||||
|
||||
nodeCategoryStorage.clear();
|
||||
|
||||
// Add all achievements to the node storage
|
||||
for (auto &[categoryName, achievements] : getAchievements()) {
|
||||
auto &nodes = nodeCategoryStorage[categoryName];
|
||||
|
||||
for (auto &[achievementName, achievement] : achievements) {
|
||||
nodes.emplace_back(achievement.get());
|
||||
}
|
||||
}
|
||||
|
||||
return nodeCategoryStorage;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<AchievementManager::AchievementNode*>>& AchievementManager::getAchievementStartNodes(bool rebuild) {
|
||||
static std::unordered_map<std::string, std::vector<AchievementNode*>> startNodes;
|
||||
|
||||
if (!startNodes.empty() || !rebuild)
|
||||
return startNodes;
|
||||
|
||||
auto &nodeCategoryStorage = getAchievementNodes();
|
||||
|
||||
startNodes.clear();
|
||||
|
||||
// Add all parents and children to the nodes
|
||||
for (auto &[categoryName, achievements] : nodeCategoryStorage) {
|
||||
for (auto &achievementNode : achievements) {
|
||||
for (auto &requirement : achievementNode.achievement->getRequirements()) {
|
||||
for (auto &[requirementCategoryName, requirementAchievements] : nodeCategoryStorage) {
|
||||
auto iter = std::find_if(requirementAchievements.begin(), requirementAchievements.end(), [&requirement](auto &node) {
|
||||
return node.achievement->getUnlocalizedName() == requirement;
|
||||
});
|
||||
|
||||
if (iter != requirementAchievements.end()) {
|
||||
achievementNode.parents.emplace_back(&*iter);
|
||||
iter->children.emplace_back(&achievementNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &requirement : achievementNode.achievement->getVisibilityRequirements()) {
|
||||
for (auto &[requirementCategoryName, requirementAchievements] : nodeCategoryStorage) {
|
||||
auto iter = std::find_if(requirementAchievements.begin(), requirementAchievements.end(), [&requirement](auto &node) {
|
||||
return node.achievement->getUnlocalizedName() == requirement;
|
||||
});
|
||||
|
||||
if (iter != requirementAchievements.end()) {
|
||||
achievementNode.visibilityParents.emplace_back(&*iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &[categoryName, achievements] : nodeCategoryStorage) {
|
||||
for (auto &achievementNode : achievements) {
|
||||
if (!achievementNode.hasParents()) {
|
||||
startNodes[categoryName].emplace_back(&achievementNode);
|
||||
}
|
||||
|
||||
for (const auto &parent : achievementNode.parents) {
|
||||
if (parent->achievement->getUnlocalizedCategory() != achievementNode.achievement->getUnlocalizedCategory())
|
||||
startNodes[categoryName].emplace_back(&achievementNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return startNodes;
|
||||
}
|
||||
|
||||
void AchievementManager::unlockAchievement(const std::string &unlocalizedCategory, const std::string &unlocalizedName) {
|
||||
auto &categories = getAchievements();
|
||||
|
||||
auto categoryIter = categories.find(unlocalizedCategory);
|
||||
if (categoryIter == categories.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &[categoryName, achievements] = *categoryIter;
|
||||
|
||||
auto achievementIter = achievements.find(unlocalizedName);
|
||||
|
||||
if (achievementIter == achievements.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &nodes = getAchievementNodes()[categoryName];
|
||||
|
||||
for (const auto &node : nodes) {
|
||||
auto &achievement = node.achievement;
|
||||
|
||||
if (achievement->getUnlocalizedCategory() != unlocalizedCategory) {
|
||||
continue;
|
||||
}
|
||||
if (achievement->getUnlocalizedName() != unlocalizedName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.achievement->isUnlocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &requirement : node.parents) {
|
||||
if (!requirement->achievement->isUnlocked()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
achievement->setUnlocked(true);
|
||||
|
||||
if (achievement->isUnlocked())
|
||||
EventManager::post<EventAchievementUnlocked>(*achievement);
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementManager::clear() {
|
||||
getAchievements().clear();
|
||||
getAchievementStartNodes(false).clear();
|
||||
getAchievementNodes(false).clear();
|
||||
}
|
||||
|
||||
void AchievementManager::clearTemporary() {
|
||||
auto &categories = getAchievements();
|
||||
for (auto &[categoryName, achievements] : categories) {
|
||||
std::erase_if(achievements, [](auto &data) {
|
||||
auto &[achievementName, achievement] = data;
|
||||
return achievement->isTemporary();
|
||||
});
|
||||
}
|
||||
|
||||
std::erase_if(categories, [](auto &data) {
|
||||
auto &[categoryName, achievements] = data;
|
||||
return achievements.empty();
|
||||
});
|
||||
|
||||
getAchievementStartNodes(false).clear();
|
||||
getAchievementNodes(false).clear();
|
||||
}
|
||||
|
||||
void AchievementManager::achievementAdded() {
|
||||
getAchievementStartNodes(false).clear();
|
||||
getAchievementNodes(false).clear();
|
||||
}
|
||||
|
||||
constexpr static auto AchievementsFile = "achievements.json";
|
||||
|
||||
void AchievementManager::loadProgress() {
|
||||
for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
||||
auto path = directory / AchievementsFile;
|
||||
|
||||
if (!wolv::io::fs::exists(path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
||||
|
||||
if (!file.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
auto json = nlohmann::json::parse(file.readString());
|
||||
|
||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||
for (const auto &[achievementName, achievement] : achievements) {
|
||||
try {
|
||||
achievement->setProgress(json[categoryName][achievementName]);
|
||||
} catch (const std::exception &e) {
|
||||
log::warn("Failed to load achievement progress for '{}::{}': {}", categoryName, achievementName, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Failed to load achievements: {}", e.what());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementManager::storeProgress() {
|
||||
for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
||||
auto path = directory / AchievementsFile;
|
||||
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
|
||||
if (!file.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nlohmann::json json;
|
||||
|
||||
for (const auto &[categoryName, achievements] : getAchievements()) {
|
||||
json[categoryName] = nlohmann::json::object();
|
||||
|
||||
for (const auto &[achievementName, achievement] : achievements) {
|
||||
json[categoryName][achievementName] = achievement->getProgress();
|
||||
}
|
||||
}
|
||||
|
||||
file.writeString(json.dump(4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <wolv/io/file.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -65,6 +66,11 @@ namespace hex {
|
||||
}
|
||||
|
||||
void store() {
|
||||
// During a crash settings can be empty, causing them to be overwritten.
|
||||
if(getSettingsData().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
||||
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Create);
|
||||
|
||||
@@ -301,7 +307,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
runtime.addDefine("__IMHEX__");
|
||||
runtime.addDefine("__IMHEX_VERSION__", IMHEX_VERSION);
|
||||
runtime.addDefine("__IMHEX_VERSION__", ImHexApi::System::getImHexVersion());
|
||||
}
|
||||
|
||||
void addPragma(const std::string &name, const pl::api::PragmaHandler &handler) {
|
||||
@@ -336,6 +342,11 @@ namespace hex {
|
||||
impl::getVisualizers()[name] = impl::Visualizer { parameterCount, function };
|
||||
}
|
||||
|
||||
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, u32 parameterCount) {
|
||||
log::debug("Registered new inline pattern visualizer function: {}", name);
|
||||
impl::getInlineVisualizers()[name] = impl::Visualizer { parameterCount, function };
|
||||
}
|
||||
|
||||
|
||||
namespace impl {
|
||||
|
||||
@@ -345,6 +356,12 @@ namespace hex {
|
||||
return visualizers;
|
||||
}
|
||||
|
||||
std::map<std::string, impl::Visualizer> &getInlineVisualizers() {
|
||||
static std::map<std::string, impl::Visualizer> visualizers;
|
||||
|
||||
return visualizers;
|
||||
}
|
||||
|
||||
std::map<std::string, pl::api::PragmaHandler> &getPragmas() {
|
||||
static std::map<std::string, pl::api::PragmaHandler> pragmas;
|
||||
|
||||
|
||||
@@ -2,7 +2,17 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
EventManager::EventList EventManager::s_events;
|
||||
std::map<void *, EventManager::EventList::iterator> EventManager::s_tokenStore;
|
||||
std::map<void *, EventManager::EventList::iterator>& EventManager::getTokenStore() {
|
||||
static std::map<void *, EventManager::EventList::iterator> tokenStore;
|
||||
|
||||
return tokenStore;
|
||||
}
|
||||
|
||||
EventManager::EventList& EventManager::getEvents() {
|
||||
static EventManager::EventList events;
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -255,6 +255,10 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
i64 getCurrentProviderIndex() {
|
||||
return s_currentProvider;
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
return !s_providers.empty() && s_currentProvider >= 0 && s_currentProvider < i64(s_providers.size());
|
||||
}
|
||||
@@ -335,8 +339,16 @@ namespace hex {
|
||||
|
||||
namespace ImHexApi::System {
|
||||
|
||||
|
||||
namespace impl {
|
||||
|
||||
// default to true means we forward to ourselves by default
|
||||
static bool s_isMainInstance = true;
|
||||
|
||||
void setMainInstanceStatus(bool status) {
|
||||
s_isMainInstance = status;
|
||||
}
|
||||
|
||||
static ImVec2 s_mainWindowPos;
|
||||
static ImVec2 s_mainWindowSize;
|
||||
void setMainWindowPosition(i32 x, i32 y) {
|
||||
@@ -364,13 +376,6 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
static ProgramArguments s_programArguments;
|
||||
void setProgramArguments(int argc, char **argv, char **envp) {
|
||||
s_programArguments.argc = argc;
|
||||
s_programArguments.argv = argv;
|
||||
s_programArguments.envp = envp;
|
||||
}
|
||||
|
||||
static bool s_borderlessWindowMode;
|
||||
void setBorderlessWindowMode(bool enabled) {
|
||||
s_borderlessWindowMode = enabled;
|
||||
@@ -405,6 +410,10 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
bool isMainInstance() {
|
||||
return impl::s_isMainInstance;
|
||||
}
|
||||
|
||||
void closeImHex(bool noQuestions) {
|
||||
EventManager::post<RequestCloseImHex>(noQuestions);
|
||||
}
|
||||
@@ -418,25 +427,6 @@ namespace hex {
|
||||
EventManager::post<EventSetTaskBarIconState>(u32(state), u32(type), progress);
|
||||
}
|
||||
|
||||
const ProgramArguments &getProgramArguments() {
|
||||
return impl::s_programArguments;
|
||||
}
|
||||
|
||||
std::optional<std::u8string> getProgramArgument(int index) {
|
||||
if (index >= impl::s_programArguments.argc) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
std::wstring wideArg = ::CommandLineToArgvW(::GetCommandLineW(), &impl::s_programArguments.argc)[index];
|
||||
std::string byteArg = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(wideArg);
|
||||
|
||||
return std::u8string(byteArg.begin(), byteArg.end());
|
||||
#else
|
||||
return std::u8string(reinterpret_cast<const char8_t *>(impl::s_programArguments.argv[index]));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static float s_targetFPS = 14.0F;
|
||||
|
||||
@@ -480,7 +470,7 @@ namespace hex {
|
||||
return initArgs;
|
||||
}
|
||||
|
||||
const std::fs::path &getCustomFontPath() {
|
||||
std::fs::path &getCustomFontPath() {
|
||||
return impl::s_customFontPath;
|
||||
}
|
||||
|
||||
@@ -504,13 +494,13 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
static std::vector<std::fs::path> s_additionalFolderPaths;
|
||||
const std::vector<std::fs::path> &getAdditionalFolderPaths() {
|
||||
return s_additionalFolderPaths;
|
||||
std::vector<std::fs::path> &getAdditionalFolderPaths() {
|
||||
static std::vector<std::fs::path> additionalFolderPaths;
|
||||
return additionalFolderPaths;
|
||||
}
|
||||
|
||||
void setAdditionalFolderPaths(const std::vector<std::fs::path> &paths) {
|
||||
s_additionalFolderPaths = paths;
|
||||
getAdditionalFolderPaths() = paths;
|
||||
}
|
||||
|
||||
|
||||
@@ -586,6 +576,71 @@ namespace hex {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string getImHexVersion() {
|
||||
#if defined IMHEX_VERSION
|
||||
return IMHEX_VERSION;
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string getCommitHash(bool longHash) {
|
||||
if (longHash) {
|
||||
#if defined GIT_COMMIT_HASH_LONG
|
||||
return GIT_COMMIT_HASH_LONG;
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if defined GIT_COMMIT_HASH_SHORT
|
||||
return GIT_COMMIT_HASH_SHORT;
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string getCommitBranch() {
|
||||
#if defined GIT_BRANCH
|
||||
return GIT_BRANCH;
|
||||
#else
|
||||
return "Unknown";
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ImHexApi::Messaging {
|
||||
|
||||
namespace impl {
|
||||
|
||||
std::map<std::string, MessagingHandler> &getHandlers() {
|
||||
static std::map<std::string, MessagingHandler> handlers;
|
||||
|
||||
return handlers;
|
||||
}
|
||||
|
||||
void runHandler(const std::string &eventName, const std::vector<u8> &args) {
|
||||
const auto& handlers = impl::getHandlers();
|
||||
auto matchHandler = handlers.find(eventName);
|
||||
|
||||
if (matchHandler == handlers.end()) {
|
||||
log::error("Forward event handler {} not found", eventName);
|
||||
} else {
|
||||
matchHandler->second(args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void registerHandler(const std::string &eventName, const impl::MessagingHandler &handler) {
|
||||
log::debug("Registered new forward event handler: {}", eventName);
|
||||
|
||||
impl::getHandlers().insert({ eventName, handler });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,10 +5,15 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::map<Shortcut, std::function<void()>> ShortcutManager::s_globalShortcuts;
|
||||
namespace {
|
||||
|
||||
std::map<Shortcut, std::function<void()>> s_globalShortcuts;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::function<void()> &callback) {
|
||||
ShortcutManager::s_globalShortcuts.insert({ shortcut, callback });
|
||||
s_globalShortcuts.insert({ shortcut, callback });
|
||||
}
|
||||
|
||||
void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::function<void()> &callback) {
|
||||
@@ -48,16 +53,16 @@ namespace hex {
|
||||
void ShortcutManager::processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode) {
|
||||
Shortcut pressedShortcut = getShortcut(ctrl, alt, shift, super, false, keyCode);
|
||||
|
||||
if (ShortcutManager::s_globalShortcuts.contains(pressedShortcut + AllowWhileTyping)) {
|
||||
ShortcutManager::s_globalShortcuts[pressedShortcut + AllowWhileTyping]();
|
||||
} else if (ShortcutManager::s_globalShortcuts.contains(pressedShortcut)) {
|
||||
if (s_globalShortcuts.contains(pressedShortcut + AllowWhileTyping)) {
|
||||
s_globalShortcuts[pressedShortcut + AllowWhileTyping]();
|
||||
} else if (s_globalShortcuts.contains(pressedShortcut)) {
|
||||
if (!ImGui::GetIO().WantTextInput)
|
||||
ShortcutManager::s_globalShortcuts[pressedShortcut]();
|
||||
s_globalShortcuts[pressedShortcut]();
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutManager::clearShortcuts() {
|
||||
ShortcutManager::s_globalShortcuts.clear();
|
||||
s_globalShortcuts.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,9 +9,14 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::optional<std::fs::path> LayoutManager::s_layoutPathToLoad;
|
||||
std::optional<std::string> LayoutManager::s_layoutStringToLoad;
|
||||
std::vector<LayoutManager::Layout> LayoutManager::s_layouts;
|
||||
namespace {
|
||||
|
||||
std::optional<std::fs::path> s_layoutPathToLoad;
|
||||
std::optional<std::string> s_layoutStringToLoad;
|
||||
std::vector<LayoutManager::Layout> s_layouts;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LayoutManager::load(const std::fs::path &path) {
|
||||
s_layoutPathToLoad = path;
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::string LangEntry::s_fallbackLanguage;
|
||||
std::map<std::string, std::string> LangEntry::s_currStrings;
|
||||
namespace {
|
||||
|
||||
std::string s_fallbackLanguage;
|
||||
std::string s_selectedLanguage;
|
||||
std::map<std::string, std::string> s_currStrings;
|
||||
|
||||
}
|
||||
|
||||
|
||||
LanguageDefinition::LanguageDefinition(std::map<std::string, std::string> &&entries) {
|
||||
for (const auto &[key, value] : entries) {
|
||||
@@ -66,7 +72,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
const std::string &LangEntry::get() const {
|
||||
auto &lang = LangEntry::s_currStrings;
|
||||
auto &lang = s_currStrings;
|
||||
if (lang.contains(this->m_unlocalizedString))
|
||||
return lang[this->m_unlocalizedString];
|
||||
else
|
||||
@@ -74,7 +80,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void LangEntry::loadLanguage(const std::string &language) {
|
||||
LangEntry::s_currStrings.clear();
|
||||
s_currStrings.clear();
|
||||
|
||||
auto &definitions = ContentRegistry::Language::impl::getLanguageDefinitions();
|
||||
|
||||
@@ -82,13 +88,15 @@ namespace hex {
|
||||
return;
|
||||
|
||||
for (auto &definition : definitions[language])
|
||||
LangEntry::s_currStrings.insert(definition.getEntries().begin(), definition.getEntries().end());
|
||||
s_currStrings.insert(definition.getEntries().begin(), definition.getEntries().end());
|
||||
|
||||
const auto fallbackLanguage = LangEntry::getFallbackLanguage();
|
||||
if (language != fallbackLanguage) {
|
||||
for (auto &definition : definitions[fallbackLanguage])
|
||||
LangEntry::s_currStrings.insert(definition.getEntries().begin(), definition.getEntries().end());
|
||||
s_currStrings.insert(definition.getEntries().begin(), definition.getEntries().end());
|
||||
}
|
||||
|
||||
s_selectedLanguage = language;
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string> &LangEntry::getSupportedLanguages() {
|
||||
@@ -96,15 +104,20 @@ namespace hex {
|
||||
}
|
||||
|
||||
void LangEntry::setFallbackLanguage(const std::string &language) {
|
||||
LangEntry::s_fallbackLanguage = language;
|
||||
s_fallbackLanguage = language;
|
||||
}
|
||||
|
||||
const std::string &LangEntry::getFallbackLanguage() {
|
||||
return LangEntry::s_fallbackLanguage;
|
||||
return s_fallbackLanguage;
|
||||
}
|
||||
|
||||
void LangEntry::resetLanguageStrings() {
|
||||
LangEntry::s_currStrings.clear();
|
||||
s_currStrings.clear();
|
||||
s_selectedLanguage.clear();
|
||||
}
|
||||
|
||||
const std::string &LangEntry::getSelectedLanguage() {
|
||||
return s_selectedLanguage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <hex/api/plugin_manager.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@@ -14,7 +15,7 @@ namespace hex {
|
||||
#if defined(OS_WINDOWS)
|
||||
this->m_handle = LoadLibraryW(path.c_str());
|
||||
|
||||
if (this->m_handle == nullptr) {
|
||||
if (this->m_handle == INVALID_HANDLE_VALUE || this->m_handle == nullptr) {
|
||||
log::error("LoadLibraryW failed: {}!", std::system_category().message(::GetLastError()));
|
||||
return;
|
||||
}
|
||||
@@ -34,6 +35,7 @@ namespace hex {
|
||||
this->m_getCompatibleVersionFunction = getPluginFunction<GetCompatibleVersionFunc>("getCompatibleVersion");
|
||||
this->m_setImGuiContextFunction = getPluginFunction<SetImGuiContextFunc>("setImGuiContext");
|
||||
this->m_isBuiltinPluginFunction = getPluginFunction<IsBuiltinPluginFunc>("isBuiltinPlugin");
|
||||
this->m_getSubCommandsFunction = getPluginFunction<GetSubCommandsFunc>("getSubCommands");
|
||||
}
|
||||
|
||||
Plugin::Plugin(Plugin &&other) noexcept {
|
||||
@@ -47,6 +49,7 @@ namespace hex {
|
||||
this->m_getCompatibleVersionFunction = other.m_getCompatibleVersionFunction;
|
||||
this->m_setImGuiContextFunction = other.m_setImGuiContextFunction;
|
||||
this->m_isBuiltinPluginFunction = other.m_isBuiltinPluginFunction;
|
||||
this->m_getSubCommandsFunction = other.m_getSubCommandsFunction;
|
||||
|
||||
other.m_handle = nullptr;
|
||||
other.m_initializePluginFunction = nullptr;
|
||||
@@ -56,6 +59,7 @@ namespace hex {
|
||||
other.m_getCompatibleVersionFunction = nullptr;
|
||||
other.m_setImGuiContextFunction = nullptr;
|
||||
other.m_isBuiltinPluginFunction = nullptr;
|
||||
other.m_getSubCommandsFunction = nullptr;
|
||||
}
|
||||
|
||||
Plugin::~Plugin() {
|
||||
@@ -72,14 +76,28 @@ namespace hex {
|
||||
if (this->m_handle == nullptr)
|
||||
return false;
|
||||
|
||||
const auto pluginName = wolv::util::toUTF8String(this->m_path.filename());
|
||||
|
||||
const auto requestedVersion = getCompatibleVersion();
|
||||
if (requestedVersion != IMHEX_VERSION) {
|
||||
log::error("Refused to load plugin '{}' which was built for a different version of ImHex: '{}'", wolv::util::toUTF8String(this->m_path.filename()), requestedVersion);
|
||||
return false;
|
||||
if (requestedVersion != ImHexApi::System::getImHexVersion()) {
|
||||
if (requestedVersion.empty()) {
|
||||
log::warn("Plugin '{}' did not specify a compatible version, assuming it is compatible with the current version of ImHex.", wolv::util::toUTF8String(this->m_path.filename()));
|
||||
} else {
|
||||
log::error("Refused to load plugin '{}' which was built for a different version of ImHex: '{}'", wolv::util::toUTF8String(this->m_path.filename()), requestedVersion);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_initializePluginFunction != nullptr) {
|
||||
this->m_initializePluginFunction();
|
||||
try {
|
||||
this->m_initializePluginFunction();
|
||||
} catch (const std::exception &e) {
|
||||
log::error("Plugin '{}' threw an exception on init: {}", pluginName, e.what());
|
||||
return false;
|
||||
} catch (...) {
|
||||
log::error("Plugin '{}' threw an exception on init", pluginName);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -136,6 +154,14 @@ namespace hex {
|
||||
return this->m_initialized;
|
||||
}
|
||||
|
||||
std::span<SubCommand> Plugin::getSubCommands() const {
|
||||
if (this->m_getSubCommandsFunction != nullptr) {
|
||||
auto result = this->m_getSubCommandsFunction();
|
||||
return *reinterpret_cast<std::vector<SubCommand>*>(result);
|
||||
} else
|
||||
return { };
|
||||
}
|
||||
|
||||
|
||||
void *Plugin::getPluginFunction(const std::string &symbol) {
|
||||
#if defined(OS_WINDOWS)
|
||||
@@ -146,34 +172,42 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
std::fs::path PluginManager::s_pluginFolder;
|
||||
std::vector<Plugin> PluginManager::s_plugins;
|
||||
namespace {
|
||||
|
||||
std::fs::path s_pluginFolder;
|
||||
std::vector<Plugin> s_plugins;
|
||||
|
||||
}
|
||||
|
||||
bool PluginManager::load(const std::fs::path &pluginFolder) {
|
||||
if (!wolv::io::fs::exists(pluginFolder))
|
||||
return false;
|
||||
|
||||
PluginManager::s_pluginFolder = pluginFolder;
|
||||
s_pluginFolder = pluginFolder;
|
||||
|
||||
for (auto &pluginPath : std::fs::directory_iterator(pluginFolder)) {
|
||||
if (pluginPath.is_regular_file() && pluginPath.path().extension() == ".hexplug")
|
||||
PluginManager::s_plugins.emplace_back(pluginPath.path());
|
||||
s_plugins.emplace_back(pluginPath.path());
|
||||
}
|
||||
|
||||
if (PluginManager::s_plugins.empty())
|
||||
if (s_plugins.empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PluginManager::unload() {
|
||||
PluginManager::s_plugins.clear();
|
||||
PluginManager::s_pluginFolder.clear();
|
||||
s_plugins.clear();
|
||||
s_pluginFolder.clear();
|
||||
}
|
||||
|
||||
void PluginManager::reload() {
|
||||
PluginManager::unload();
|
||||
PluginManager::load(PluginManager::s_pluginFolder);
|
||||
PluginManager::load(s_pluginFolder);
|
||||
}
|
||||
|
||||
const std::vector<Plugin> &PluginManager::getPlugins() {
|
||||
return s_plugins;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,44 +11,57 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::vector<ProjectFile::Handler> ProjectFile::s_handlers;
|
||||
std::vector<ProjectFile::ProviderHandler> ProjectFile::s_providerHandlers;
|
||||
namespace {
|
||||
|
||||
std::fs::path ProjectFile::s_currProjectPath;
|
||||
std::vector<ProjectFile::Handler> s_handlers;
|
||||
std::vector<ProjectFile::ProviderHandler> s_providerHandlers;
|
||||
|
||||
std::fs::path s_currProjectPath;
|
||||
|
||||
std::function<bool(const std::fs::path&)> s_loadProjectFunction;
|
||||
std::function<bool(std::optional<std::fs::path>, bool)> s_storeProjectFunction;
|
||||
|
||||
}
|
||||
|
||||
std::function<bool(const std::fs::path&)> ProjectFile::s_loadProjectFunction;
|
||||
std::function<bool(std::optional<std::fs::path>)> ProjectFile::s_storeProjectFunction;
|
||||
|
||||
void ProjectFile::setProjectFunctions(
|
||||
const std::function<bool(const std::fs::path&)> &loadFun,
|
||||
const std::function<bool(std::optional<std::fs::path>)> &storeFun
|
||||
const std::function<bool(std::optional<std::fs::path>, bool)> &storeFun
|
||||
) {
|
||||
ProjectFile::s_loadProjectFunction = loadFun;
|
||||
ProjectFile::s_storeProjectFunction = storeFun;
|
||||
s_loadProjectFunction = loadFun;
|
||||
s_storeProjectFunction = storeFun;
|
||||
}
|
||||
|
||||
bool ProjectFile::load(const std::fs::path &filePath) {
|
||||
return s_loadProjectFunction(filePath);
|
||||
}
|
||||
|
||||
bool ProjectFile::store(std::optional<std::fs::path> filePath) {
|
||||
return s_storeProjectFunction(filePath);
|
||||
bool ProjectFile::store(std::optional<std::fs::path> filePath, bool updateLocation) {
|
||||
return s_storeProjectFunction(filePath, updateLocation);
|
||||
}
|
||||
|
||||
bool ProjectFile::hasPath() {
|
||||
return !ProjectFile::s_currProjectPath.empty();
|
||||
return !s_currProjectPath.empty();
|
||||
}
|
||||
|
||||
void ProjectFile::clearPath() {
|
||||
ProjectFile::s_currProjectPath.clear();
|
||||
s_currProjectPath.clear();
|
||||
}
|
||||
|
||||
std::fs::path ProjectFile::getPath() {
|
||||
return ProjectFile::s_currProjectPath;
|
||||
return s_currProjectPath;
|
||||
}
|
||||
|
||||
void ProjectFile::setPath(const std::fs::path &path) {
|
||||
ProjectFile::s_currProjectPath = path;
|
||||
s_currProjectPath = path;
|
||||
}
|
||||
|
||||
std::vector<ProjectFile::Handler> &ProjectFile::getHandlers() {
|
||||
return s_handlers;
|
||||
}
|
||||
|
||||
std::vector<ProjectFile::ProviderHandler> &ProjectFile::getProviderHandlers() {
|
||||
return s_providerHandlers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,15 +14,21 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::mutex TaskManager::s_deferredCallsMutex, TaskManager::s_tasksFinishedMutex;
|
||||
namespace {
|
||||
|
||||
std::list<std::shared_ptr<Task>> TaskManager::s_tasks, TaskManager::s_taskQueue;
|
||||
std::list<std::function<void()>> TaskManager::s_deferredCalls;
|
||||
std::list<std::function<void()>> TaskManager::s_tasksFinishedCallbacks;
|
||||
std::mutex s_deferredCallsMutex, s_tasksFinishedMutex;
|
||||
|
||||
std::list<std::shared_ptr<Task>> s_tasks, s_taskQueue;
|
||||
std::list<Timer> s_timers;
|
||||
std::list<std::function<void()>> s_deferredCalls;
|
||||
std::list<std::function<void()>> s_tasksFinishedCallbacks;
|
||||
|
||||
std::mutex s_queueMutex;
|
||||
std::condition_variable s_jobCondVar;
|
||||
std::vector<std::jthread> s_workers;
|
||||
|
||||
}
|
||||
|
||||
std::mutex TaskManager::s_queueMutex;
|
||||
std::condition_variable TaskManager::s_jobCondVar;
|
||||
std::vector<std::jthread> TaskManager::s_workers;
|
||||
|
||||
static void setThreadName(const std::string &name) {
|
||||
#if defined(OS_WINDOWS)
|
||||
@@ -210,19 +216,19 @@ namespace hex {
|
||||
log::debug("Initializing task manager thread pool with {} workers.", threadCount);
|
||||
|
||||
for (u32 i = 0; i < threadCount; i++)
|
||||
TaskManager::s_workers.emplace_back(TaskManager::runner);
|
||||
s_workers.emplace_back(TaskManager::runner);
|
||||
}
|
||||
|
||||
void TaskManager::exit() {
|
||||
for (auto &task : TaskManager::s_tasks)
|
||||
for (auto &task : s_tasks)
|
||||
task->interrupt();
|
||||
|
||||
for (auto &thread : TaskManager::s_workers)
|
||||
for (auto &thread : s_workers)
|
||||
thread.request_stop();
|
||||
|
||||
s_jobCondVar.notify_all();
|
||||
|
||||
TaskManager::s_workers.clear();
|
||||
s_workers.clear();
|
||||
}
|
||||
|
||||
void TaskManager::runner(const std::stop_token &stopToken) {
|
||||
@@ -295,12 +301,17 @@ namespace hex {
|
||||
call();
|
||||
s_tasksFinishedCallbacks.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::list<std::shared_ptr<Task>> &TaskManager::getRunningTasks() {
|
||||
return s_tasks;
|
||||
}
|
||||
|
||||
std::list<Timer> &TaskManager::getTimers() {
|
||||
return s_timers;
|
||||
}
|
||||
|
||||
size_t TaskManager::getRunningTaskCount() {
|
||||
std::unique_lock lock(s_queueMutex);
|
||||
|
||||
@@ -331,6 +342,12 @@ namespace hex {
|
||||
call();
|
||||
|
||||
s_deferredCalls.clear();
|
||||
|
||||
for (const auto &timer : s_timers) {
|
||||
if (timer.elapseTime >= std::chrono::steady_clock::now()) {
|
||||
timer.callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskManager::runWhenTasksFinished(const std::function<void()> &function) {
|
||||
@@ -339,4 +356,8 @@ namespace hex {
|
||||
s_tasksFinishedCallbacks.push_back(function);
|
||||
}
|
||||
|
||||
void TaskManager::doAfter(std::chrono::duration<i64> duration, const std::function<void()> &function) {
|
||||
s_timers.push_back({ std::chrono::steady_clock::now() + duration, function });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,11 +9,16 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::map<std::string, nlohmann::json> ThemeManager::s_themes;
|
||||
std::map<std::string, ThemeManager::ThemeHandler> ThemeManager::s_themeHandlers;
|
||||
std::map<std::string, ThemeManager::StyleHandler> ThemeManager::s_styleHandlers;
|
||||
std::string ThemeManager::s_imagePostfix;
|
||||
std::string ThemeManager::s_currTheme;
|
||||
namespace {
|
||||
|
||||
std::map<std::string, nlohmann::json> s_themes;
|
||||
std::map<std::string, ThemeManager::ThemeHandler> s_themeHandlers;
|
||||
std::map<std::string, ThemeManager::StyleHandler> s_styleHandlers;
|
||||
std::string s_imageTheme;
|
||||
std::string s_currTheme;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function<ImColor(u32)> &getFunction, const std::function<void(u32, ImColor)> &setFunction) {
|
||||
s_themeHandlers[name] = { colorMap, getFunction, setFunction };
|
||||
@@ -62,7 +67,7 @@ namespace hex {
|
||||
nlohmann::json ThemeManager::exportCurrentTheme(const std::string &name) {
|
||||
nlohmann::json theme = {
|
||||
{ "name", name },
|
||||
{ "image_postfix", s_imagePostfix },
|
||||
{ "image_theme", s_imageTheme },
|
||||
{ "colors", {} },
|
||||
{ "styles", {} },
|
||||
{ "base", s_currTheme }
|
||||
@@ -174,11 +179,12 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
if (theme.contains("image_postfix")) {
|
||||
if (theme["image_postfix"].is_string()) {
|
||||
s_imagePostfix = theme["image_postfix"].get<std::string>();
|
||||
if (theme.contains("image_theme")) {
|
||||
if (theme["image_theme"].is_string()) {
|
||||
s_imageTheme = theme["image_theme"].get<std::string>();
|
||||
} else {
|
||||
hex::log::error("Theme '{}' has invalid image postfix!", name);
|
||||
hex::log::error("Theme '{}' has invalid image theme!", name);
|
||||
s_imageTheme = "dark";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,8 +193,8 @@ namespace hex {
|
||||
EventManager::post<EventThemeChanged>();
|
||||
}
|
||||
|
||||
const std::string &ThemeManager::getThemeImagePostfix() {
|
||||
return s_imagePostfix;
|
||||
const std::string &ThemeManager::getImageTheme() {
|
||||
return s_imageTheme;
|
||||
}
|
||||
|
||||
std::vector<std::string> ThemeManager::getThemeNames() {
|
||||
@@ -200,11 +206,20 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ThemeManager::reset() {
|
||||
ThemeManager::s_themes.clear();
|
||||
ThemeManager::s_styleHandlers.clear();
|
||||
ThemeManager::s_themeHandlers.clear();
|
||||
ThemeManager::s_imagePostfix.clear();
|
||||
ThemeManager::s_currTheme.clear();
|
||||
s_themes.clear();
|
||||
s_styleHandlers.clear();
|
||||
s_themeHandlers.clear();
|
||||
s_imageTheme.clear();
|
||||
s_currTheme.clear();
|
||||
}
|
||||
|
||||
|
||||
std::map<std::string, ThemeManager::ThemeHandler> &ThemeManager::getThemeHandlers() {
|
||||
return s_themeHandlers;
|
||||
}
|
||||
|
||||
std::map<std::string, ThemeManager::StyleHandler> &ThemeManager::getStyleHandlers() {
|
||||
return s_styleHandlers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,9 +3,14 @@
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
int Attribute::s_idCounter = 1;
|
||||
namespace {
|
||||
|
||||
Attribute::Attribute(IOType ioType, Type type, std::string unlocalizedName) : m_id(Attribute::s_idCounter++), m_ioType(ioType), m_type(type), m_unlocalizedName(std::move(unlocalizedName)) {
|
||||
int s_idCounter = 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Attribute::Attribute(IOType ioType, Type type, std::string unlocalizedName) : m_id(s_idCounter++), m_ioType(ioType), m_type(type), m_unlocalizedName(std::move(unlocalizedName)) {
|
||||
}
|
||||
|
||||
Attribute::~Attribute() {
|
||||
@@ -13,4 +18,9 @@ namespace hex::dp {
|
||||
attr->removeConnectedAttribute(linkId);
|
||||
}
|
||||
|
||||
void Attribute::setIdCounter(int id) {
|
||||
if (id > s_idCounter)
|
||||
s_idCounter = id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,9 +3,16 @@
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
int Link::s_idCounter = 1;
|
||||
namespace {
|
||||
|
||||
Link::Link(int from, int to) : m_id(Link::s_idCounter++), m_from(from), m_to(to) { }
|
||||
int s_idCounter = 1;
|
||||
|
||||
}
|
||||
|
||||
Link::Link(int from, int to) : m_id(s_idCounter++), m_from(from), m_to(to) { }
|
||||
|
||||
void Link::setIdCounter(int id) {
|
||||
if (id > s_idCounter)
|
||||
s_idCounter = id;
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,13 @@
|
||||
|
||||
namespace hex::dp {
|
||||
|
||||
int Node::s_idCounter = 1;
|
||||
namespace {
|
||||
|
||||
Node::Node(std::string unlocalizedTitle, std::vector<Attribute> attributes) : m_id(Node::s_idCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) {
|
||||
int s_idCounter = 1;
|
||||
|
||||
}
|
||||
|
||||
Node::Node(std::string unlocalizedTitle, std::vector<Attribute> attributes) : m_id(s_idCounter++), m_unlocalizedTitle(std::move(unlocalizedTitle)), m_attributes(std::move(attributes)) {
|
||||
for (auto &attr : this->m_attributes)
|
||||
attr.setParentNode(this);
|
||||
}
|
||||
@@ -60,7 +64,7 @@ namespace hex::dp {
|
||||
return *reinterpret_cast<i128 *>(outputData.data());
|
||||
}
|
||||
|
||||
const long double& Node::getFloatOnInput(u32 index) {
|
||||
const double& Node::getFloatOnInput(u32 index) {
|
||||
auto attribute = this->getConnectedInputAttribute(index);
|
||||
|
||||
auto &outputData = [&] -> std::vector<u8>& {
|
||||
@@ -80,10 +84,10 @@ namespace hex::dp {
|
||||
if (outputData.empty())
|
||||
throwNodeError("No data available at connected attribute");
|
||||
|
||||
if (outputData.size() < sizeof(long double))
|
||||
if (outputData.size() < sizeof(double))
|
||||
throwNodeError("Not enough data provided for float");
|
||||
|
||||
return *reinterpret_cast<long double *>(outputData.data());
|
||||
return *reinterpret_cast<double *>(outputData.data());
|
||||
}
|
||||
|
||||
void Node::setBufferOnOutput(u32 index, std::span<const u8> data) {
|
||||
@@ -95,6 +99,9 @@ namespace hex::dp {
|
||||
if (attribute.getIOType() != Attribute::IOType::Out)
|
||||
throwNodeError("Tried to set output data of an input attribute!");
|
||||
|
||||
if (attribute.getType() != Attribute::Type::Buffer)
|
||||
throwNodeError("Tried to set buffer on non-buffer attribute!");
|
||||
|
||||
attribute.getOutputData() = { data.begin(), data.end() };
|
||||
}
|
||||
|
||||
@@ -107,13 +114,16 @@ namespace hex::dp {
|
||||
if (attribute.getIOType() != Attribute::IOType::Out)
|
||||
throwNodeError("Tried to set output data of an input attribute!");
|
||||
|
||||
if (attribute.getType() != Attribute::Type::Integer)
|
||||
throwNodeError("Tried to set integer on non-integer attribute!");
|
||||
|
||||
std::vector<u8> buffer(sizeof(integer), 0);
|
||||
std::memcpy(buffer.data(), &integer, sizeof(integer));
|
||||
|
||||
attribute.getOutputData() = buffer;
|
||||
}
|
||||
|
||||
void Node::setFloatOnOutput(u32 index, long double floatingPoint) {
|
||||
void Node::setFloatOnOutput(u32 index, double floatingPoint) {
|
||||
if (index >= this->getAttributes().size())
|
||||
throwNodeError("Attribute index out of bounds!");
|
||||
|
||||
@@ -122,6 +132,9 @@ namespace hex::dp {
|
||||
if (attribute.getIOType() != Attribute::IOType::Out)
|
||||
throwNodeError("Tried to set output data of an input attribute!");
|
||||
|
||||
if (attribute.getType() != Attribute::Type::Float)
|
||||
throwNodeError("Tried to set float on non-float attribute!");
|
||||
|
||||
std::vector<u8> buffer(sizeof(floatingPoint), 0);
|
||||
std::memcpy(buffer.data(), &floatingPoint, sizeof(floatingPoint));
|
||||
|
||||
@@ -136,4 +149,9 @@ namespace hex::dp {
|
||||
this->m_overlay->getData() = data;
|
||||
}
|
||||
|
||||
void Node::setIdCounter(int id) {
|
||||
if (id > s_idCounter)
|
||||
s_idCounter = id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -390,16 +390,22 @@ namespace hex::crypt {
|
||||
std::vector<u8> decode16(const std::string &input) {
|
||||
std::vector<u8> output(input.length() / 2, 0x00);
|
||||
|
||||
|
||||
mbedtls_mpi ctx;
|
||||
mbedtls_mpi_init(&ctx);
|
||||
|
||||
ON_SCOPE_EXIT { mbedtls_mpi_free(&ctx); };
|
||||
|
||||
if (mbedtls_mpi_read_string(&ctx, 16, input.c_str()))
|
||||
return {};
|
||||
// read buffered
|
||||
constexpr static auto BufferSize = 0x100;
|
||||
for (size_t offset = 0; offset < input.size(); offset += BufferSize) {
|
||||
std::string inputPart = input.substr(offset, std::min<size_t>(BufferSize, input.size() - offset));
|
||||
if (mbedtls_mpi_read_string(&ctx, 16, inputPart.c_str()))
|
||||
return {};
|
||||
|
||||
if (mbedtls_mpi_write_binary(&ctx, output.data(), output.size()))
|
||||
return {};
|
||||
if (mbedtls_mpi_write_binary(&ctx, output.data() + offset / 2, inputPart.size() / 2))
|
||||
return {};
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace hex {
|
||||
this->m_tableContent = other.m_tableContent;
|
||||
this->m_longestSequence = other.m_longestSequence;
|
||||
this->m_valid = other.m_valid;
|
||||
this->m_name = other.m_name;
|
||||
}
|
||||
|
||||
EncodingFile::EncodingFile(EncodingFile &&other) {
|
||||
@@ -23,6 +24,7 @@ namespace hex {
|
||||
this->m_tableContent = std::move(other.m_tableContent);
|
||||
this->m_longestSequence = other.m_longestSequence;
|
||||
this->m_valid = other.m_valid;
|
||||
this->m_name = std::move(other.m_name);
|
||||
}
|
||||
|
||||
EncodingFile::EncodingFile(Type type, const std::fs::path &path) : EncodingFile() {
|
||||
@@ -35,6 +37,14 @@ namespace hex {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
this->m_name = path.stem().string();
|
||||
this->m_name = wolv::util::replaceStrings(this->m_name, "_", " ");
|
||||
|
||||
if (!this->m_name.empty())
|
||||
this->m_name[0] = std::toupper(this->m_name[0]);
|
||||
}
|
||||
|
||||
this->m_valid = true;
|
||||
}
|
||||
|
||||
@@ -47,6 +57,7 @@ namespace hex {
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_name = "Unknown";
|
||||
this->m_valid = true;
|
||||
}
|
||||
|
||||
@@ -56,6 +67,7 @@ namespace hex {
|
||||
this->m_tableContent = other.m_tableContent;
|
||||
this->m_longestSequence = other.m_longestSequence;
|
||||
this->m_valid = other.m_valid;
|
||||
this->m_name = other.m_name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -65,6 +77,7 @@ namespace hex {
|
||||
this->m_tableContent = std::move(other.m_tableContent);
|
||||
this->m_longestSequence = other.m_longestSequence;
|
||||
this->m_valid = other.m_valid;
|
||||
this->m_name = std::move(other.m_name);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils_linux.hpp>
|
||||
|
||||
#include <xdg.hpp>
|
||||
|
||||
@@ -17,9 +18,11 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <utility>
|
||||
|
||||
#include <wolv/io/file.hpp>
|
||||
#include <wolv/io/fs.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
namespace hex::fs {
|
||||
|
||||
@@ -43,9 +46,7 @@ namespace hex::fs {
|
||||
hex::format("open {}", wolv::util::toUTF8String(filePath)).c_str()
|
||||
));
|
||||
#elif defined(OS_LINUX)
|
||||
hex::unused(system(
|
||||
hex::format("xdg-open {}", wolv::util::toUTF8String(filePath)).c_str()
|
||||
));
|
||||
executeCmd({"xdg-open", wolv::util::toUTF8String(filePath)});
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -62,9 +63,7 @@ namespace hex::fs {
|
||||
hex::format("open {}", wolv::util::toUTF8String(dirPath)).c_str()
|
||||
));
|
||||
#elif defined(OS_LINUX)
|
||||
hex::unused(system(
|
||||
hex::format("xdg-open {}", wolv::util::toUTF8String(dirPath)).c_str()
|
||||
));
|
||||
executeCmd({"xdg-open", wolv::util::toUTF8String(dirPath)});
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -87,9 +86,7 @@ namespace hex::fs {
|
||||
#elif defined(OS_LINUX)
|
||||
// fallback to only opening the folder for now
|
||||
// TODO actually select the file
|
||||
hex::unused(system(
|
||||
hex::format("xdg-open {}", wolv::util::toUTF8String(selectedFilePath.parent_path())).c_str()
|
||||
));
|
||||
executeCmd({"xdg-open", wolv::util::toUTF8String(selectedFilePath.parent_path())});
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -174,9 +171,6 @@ namespace hex::fs {
|
||||
|
||||
#endif
|
||||
|
||||
for (auto &path : paths)
|
||||
path = path / "imhex";
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
|
||||
@@ -184,6 +178,9 @@ namespace hex::fs {
|
||||
|
||||
#else
|
||||
|
||||
for (auto &path : paths)
|
||||
path = path / "imhex";
|
||||
|
||||
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
|
||||
paths.push_back(executablePath->parent_path());
|
||||
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
std::string HttpRequest::s_caCertData;
|
||||
std::string HttpRequest::s_proxyUrl;
|
||||
namespace {
|
||||
|
||||
std::string s_proxyUrl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
HttpRequest::HttpRequest(std::string method, std::string url) : m_method(std::move(method)), m_url(std::move(url)) {
|
||||
AT_FIRST_TIME {
|
||||
@@ -36,31 +40,6 @@ namespace hex {
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_XFERINFODATA, this);
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_XFERINFOFUNCTION, progressCallback);
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_PROXY, s_proxyUrl.c_str());
|
||||
|
||||
#if defined(IMHEX_USE_BUNDLED_CA)
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_CAINFO, nullptr);
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_CAPATH, nullptr);
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_SSLCERTTYPE, "PEM");
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_SSL_CTX_FUNCTION, sslCtxFunction);
|
||||
|
||||
this->m_caCert = std::make_unique<mbedtls_x509_crt>();
|
||||
curl_easy_setopt(this->m_curl, CURLOPT_SSL_CTX_DATA, this->m_caCert.get());
|
||||
#endif
|
||||
}
|
||||
|
||||
CURLcode HttpRequest::sslCtxFunction(CURL *ctx, void *sslctx, void *userData) {
|
||||
hex::unused(ctx, userData);
|
||||
|
||||
auto *cfg = static_cast<mbedtls_ssl_config *>(sslctx);
|
||||
|
||||
auto crt = static_cast<mbedtls_x509_crt*>(userData);
|
||||
mbedtls_x509_crt_init(crt);
|
||||
|
||||
mbedtls_x509_crt_parse(crt, reinterpret_cast<const u8 *>(HttpRequest::s_caCertData.data()), HttpRequest::s_caCertData.size());
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(cfg, crt, nullptr);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
size_t HttpRequest::writeToVector(void *contents, size_t size, size_t nmemb, void *userdata) {
|
||||
@@ -94,4 +73,14 @@ namespace hex {
|
||||
return request.m_canceled ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK;
|
||||
}
|
||||
|
||||
void HttpRequest::setProxy(std::string proxy) {
|
||||
s_proxyUrl = std::move(proxy);
|
||||
}
|
||||
|
||||
void HttpRequest::checkProxyErrors() {
|
||||
if (!s_proxyUrl.empty()){
|
||||
log::info("A custom proxy '{0}' is in use. Is it working correctly?", s_proxyUrl);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace hex::log::impl {
|
||||
|
||||
static wolv::io::File s_loggerFile;
|
||||
std::mutex s_loggerMutex;
|
||||
std::mutex g_loggerMutex;
|
||||
|
||||
FILE *getDestination() {
|
||||
if (s_loggerFile.isValid())
|
||||
@@ -36,4 +36,20 @@ namespace hex::log::impl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<LogEntry>& getLogEntries() {
|
||||
static std::vector<LogEntry> logEntries;
|
||||
return logEntries;
|
||||
}
|
||||
|
||||
void assertionHandler(bool expr, const char* expr_str, const char* file, int line) {
|
||||
if (!expr) {
|
||||
log::error("Assertion failed: {} at {}:{}", expr_str, file, line);
|
||||
|
||||
#if defined (DEBUG)
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <wolv/utils/guards.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
@@ -13,6 +14,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <magic.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#define MAGIC_PATH_SEPARATOR ";"
|
||||
@@ -52,7 +54,32 @@ namespace hex::magic {
|
||||
if (!magicFiles.has_value())
|
||||
return false;
|
||||
|
||||
return magic_compile(ctx, magicFiles->c_str()) == 0;
|
||||
std::array<char, 1024> cwd = { 0x00 };
|
||||
if (getcwd(cwd.data(), cwd.size()) == nullptr)
|
||||
return false;
|
||||
|
||||
std::optional<std::fs::path> magicFolder;
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
|
||||
if (std::fs::exists(dir) && fs::isPathWritable(dir)) {
|
||||
magicFolder = dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!magicFolder.has_value()) {
|
||||
log::error("Could not find a writable magic folder");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chdir(wolv::util::toUTF8String(*magicFolder).c_str()) != 0)
|
||||
return false;
|
||||
|
||||
auto result = magic_compile(ctx, magicFiles->c_str()) == 0;
|
||||
|
||||
if (chdir(cwd.data()) != 0)
|
||||
return false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string getDescription(const std::vector<u8> &data) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <hex/helpers/stacktrace.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
@@ -116,10 +118,10 @@
|
||||
static std::vector<StackFrame> result;
|
||||
|
||||
std::array<void*, 128> addresses;
|
||||
auto count = backtrace(addresses.data(), addresses.size());
|
||||
size_t count = backtrace(addresses.data(), addresses.size());
|
||||
auto functions = backtrace_symbols(addresses.data(), count);
|
||||
|
||||
for (i32 i = 0; i < count; i++)
|
||||
for (size_t i = 0; i < count; i++)
|
||||
result.push_back(StackFrame { "", functions[i], 0 });
|
||||
|
||||
return result;
|
||||
@@ -179,7 +181,7 @@
|
||||
namespace hex::stacktrace {
|
||||
|
||||
void initialize() { }
|
||||
std::vector<StackFrame> getStackTrace() { return { }; }
|
||||
std::vector<StackFrame> getStackTrace() { return { StackFrame { "??", "Stacktrace collecting not available!", 0 } }; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,13 @@ namespace hex {
|
||||
|
||||
bool Tar::contains(const std::fs::path &path) {
|
||||
mtar_header_t header;
|
||||
return mtar_find(&this->m_ctx, path.string().c_str(), &header) == MTAR_ESUCCESS;
|
||||
|
||||
auto fixedPath = path.string();
|
||||
#if defined(OS_WINDOWS)
|
||||
std::replace(fixedPath.begin(), fixedPath.end(), '\\', '/');
|
||||
#endif
|
||||
|
||||
return mtar_find(&this->m_ctx, fixedPath.c_str(), &header) == MTAR_ESUCCESS;
|
||||
}
|
||||
|
||||
std::string Tar::getOpenErrorString(){
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/helpers/utils_linux.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@@ -313,14 +314,12 @@ namespace hex {
|
||||
void runCommand(const std::string &command) {
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
auto result = system(hex::format("start {0}", command).c_str());
|
||||
hex::unused(system(hex::format("start {0}", command).c_str()));
|
||||
#elif defined(OS_MACOS)
|
||||
auto result = system(hex::format("open {0}", command).c_str());
|
||||
hex::unused(system(hex::format("open {0}", command).c_str()));
|
||||
#elif defined(OS_LINUX)
|
||||
auto result = system(hex::format("xdg-open {0}", command).c_str());
|
||||
executeCmd({"xdg-open", command});
|
||||
#endif
|
||||
|
||||
hex::unused(result);
|
||||
}
|
||||
|
||||
void openWebpage(std::string url) {
|
||||
@@ -332,8 +331,7 @@ namespace hex {
|
||||
#elif defined(OS_MACOS)
|
||||
openWebpageMacos(url.c_str());
|
||||
#elif defined(OS_LINUX)
|
||||
auto result = system(hex::format("xdg-open {0}", url).c_str());
|
||||
hex::unused(result);
|
||||
executeCmd({"xdg-open", url});
|
||||
#else
|
||||
#warning "Unknown OS, can't open webpages"
|
||||
#endif
|
||||
|
||||
27
lib/libimhex/source/helpers/utils_linux.cpp
Normal file
27
lib/libimhex/source/helpers/utils_linux.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
#include<hex/helpers/logger.hpp>
|
||||
|
||||
#include<vector>
|
||||
#include<string>
|
||||
#include<unistd.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
void executeCmd(const std::vector<std::string> &argsVector) {
|
||||
std::vector<char*> cArgsVector;
|
||||
for (const auto &str : argsVector) {
|
||||
cArgsVector.push_back(const_cast<char*>(str.c_str()));
|
||||
}
|
||||
cArgsVector.push_back(nullptr);
|
||||
|
||||
if (fork() == 0) {
|
||||
execvp(cArgsVector[0], &cArgsVector[0]);
|
||||
log::error("execvp() failed: {}", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,12 @@
|
||||
|
||||
namespace hex::prv {
|
||||
|
||||
u32 Provider::s_idCounter = 0;
|
||||
namespace {
|
||||
|
||||
u32 s_idCounter = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Provider::Provider() : m_id(s_idCounter++) {
|
||||
this->m_patches.emplace_back();
|
||||
@@ -21,9 +26,10 @@ namespace hex::prv {
|
||||
}
|
||||
|
||||
Provider::~Provider() {
|
||||
for (auto overlay : this->m_overlays)
|
||||
delete overlay;
|
||||
this->m_overlays.clear();
|
||||
|
||||
if (auto selection = ImHexApi::HexEditor::getSelection(); selection.has_value() && selection->provider == this)
|
||||
EventManager::post<EventRegionSelected>(ImHexApi::HexEditor::ProviderRegion { { 0x00, 0x00 }, nullptr });
|
||||
}
|
||||
|
||||
void Provider::read(u64 offset, void *buffer, size_t size, bool overlays) {
|
||||
@@ -138,6 +144,14 @@ namespace hex::prv {
|
||||
if (!this->isWritable())
|
||||
return;
|
||||
|
||||
this->m_patches.emplace_back();
|
||||
|
||||
for (auto &[patchAddress, patch] : getPatches()) {
|
||||
u8 value = 0x00;
|
||||
this->readRaw(patchAddress - this->getBaseAddress(), &value, 1);
|
||||
this->m_patches.back().insert({ patchAddress, value });
|
||||
}
|
||||
|
||||
for (auto &[patchAddress, patch] : getPatches()) {
|
||||
this->writeRaw(patchAddress - this->getBaseAddress(), &patch, 1);
|
||||
}
|
||||
@@ -145,19 +159,21 @@ namespace hex::prv {
|
||||
this->markDirty();
|
||||
|
||||
this->m_patches.emplace_back();
|
||||
this->m_currPatches = std::prev(this->m_patches.end());
|
||||
}
|
||||
|
||||
|
||||
Overlay *Provider::newOverlay() {
|
||||
return this->m_overlays.emplace_back(new Overlay());
|
||||
return this->m_overlays.emplace_back(std::make_unique<Overlay>()).get();
|
||||
}
|
||||
|
||||
void Provider::deleteOverlay(Overlay *overlay) {
|
||||
this->m_overlays.remove(overlay);
|
||||
delete overlay;
|
||||
this->m_overlays.remove_if([overlay](const auto &item) {
|
||||
return item.get() == overlay;
|
||||
});
|
||||
}
|
||||
|
||||
const std::list<Overlay *> &Provider::getOverlays() {
|
||||
const std::list<std::unique_ptr<Overlay>> &Provider::getOverlays() {
|
||||
return this->m_overlays;
|
||||
}
|
||||
|
||||
@@ -213,6 +229,10 @@ namespace hex::prv {
|
||||
return page;
|
||||
}
|
||||
|
||||
std::vector<Provider::Description> Provider::getDataDescription() const {
|
||||
return { };
|
||||
}
|
||||
|
||||
void Provider::addPatch(u64 offset, const void *buffer, size_t size, bool createUndo) {
|
||||
if (createUndo) {
|
||||
// Delete all patches after the current one if a modification is made while
|
||||
@@ -226,7 +246,7 @@ namespace hex::prv {
|
||||
for (u64 i = 0; i < size; i++) {
|
||||
u8 patch = reinterpret_cast<const u8 *>(buffer)[i];
|
||||
u8 originalValue = 0x00;
|
||||
this->readRaw(offset + i, &originalValue, sizeof(u8));
|
||||
this->readRaw((offset + i) - this->getBaseAddress(), &originalValue, sizeof(u8));
|
||||
|
||||
if (patch == originalValue)
|
||||
getPatches().erase(offset + i);
|
||||
@@ -356,4 +376,8 @@ namespace hex::prv {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Provider::isDumpable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
120
lib/libimhex/source/subcommands/subcommands.cpp
Normal file
120
lib/libimhex/source/subcommands/subcommands.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include<iostream>
|
||||
#include<numeric>
|
||||
#include<string_view>
|
||||
#include<ranges>
|
||||
#include<stdlib.h>
|
||||
|
||||
#include "hex/subcommands/subcommands.hpp"
|
||||
|
||||
#include <hex/api/event.hpp>
|
||||
#include <hex/api/plugin_manager.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
namespace hex::subcommands {
|
||||
|
||||
std::optional<SubCommand> findSubCommand(const std::string &arg) {
|
||||
for (auto &plugin : PluginManager::getPlugins()) {
|
||||
for (auto &subCommand : plugin.getSubCommands()) {
|
||||
if (hex::format("--{}", subCommand.commandKey) == arg) {
|
||||
return subCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void processArguments(const std::vector<std::string> &args) {
|
||||
// If no arguments, do not even try to process arguments
|
||||
// (important because this function will exit ImHex if an instance is already opened,
|
||||
// and we don't want that if no arguments were provided)
|
||||
if (args.empty()) return;
|
||||
|
||||
std::vector<std::pair<SubCommand, std::vector<std::string>>> subCommands;
|
||||
|
||||
auto argsIter = args.begin();
|
||||
|
||||
// get subcommand associated with the first argument
|
||||
std::optional<SubCommand> currentSubCommand = findSubCommand(*argsIter);
|
||||
|
||||
if (currentSubCommand) {
|
||||
argsIter++;
|
||||
// if it is a valid subcommand, remove it from the argument list
|
||||
} else {
|
||||
// if no (valid) subcommand was provided, the default one is --open
|
||||
currentSubCommand = findSubCommand("--open");
|
||||
}
|
||||
|
||||
// arguments of the current subcommand
|
||||
std::vector<std::string> currentSubCommandArgs;
|
||||
|
||||
// compute all subcommands to run
|
||||
while (argsIter != args.end()) {
|
||||
const std::string &arg = *argsIter;
|
||||
|
||||
if (arg == "--othercmd") {
|
||||
// save command to run
|
||||
if (currentSubCommand) {
|
||||
subCommands.emplace_back(*currentSubCommand, currentSubCommandArgs);
|
||||
}
|
||||
|
||||
currentSubCommand = std::nullopt;
|
||||
currentSubCommandArgs = { };
|
||||
|
||||
} else if (currentSubCommand) {
|
||||
// add current argument to the current command
|
||||
currentSubCommandArgs.push_back(arg);
|
||||
} else {
|
||||
// get next subcommand from current argument
|
||||
currentSubCommand = findSubCommand(arg);
|
||||
if (!currentSubCommand) {
|
||||
log::error("No subcommand named '{}' found", arg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
argsIter++;
|
||||
}
|
||||
|
||||
// save last command to run
|
||||
if (currentSubCommand) {
|
||||
subCommands.emplace_back(*currentSubCommand, currentSubCommandArgs);
|
||||
}
|
||||
|
||||
// run the subcommands
|
||||
for (auto& subCommandPair : subCommands) {
|
||||
subCommandPair.first.callback(subCommandPair.second);
|
||||
}
|
||||
|
||||
// exit the process if its not the main instance (the commands have been forwarded to another instance)
|
||||
if (!ImHexApi::System::isMainInstance()) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void forwardSubCommand(const std::string &cmdName, const std::vector<std::string> &args) {
|
||||
log::debug("Forwarding subcommand {} (maybe to us)", cmdName);
|
||||
std::string dataStr = std::accumulate(args.begin(), args.end(), std::string("\0"));
|
||||
|
||||
std::vector<u8> data(dataStr.begin(), dataStr.end());
|
||||
|
||||
EventManager::post<SendMessageToMainInstance>(hex::format("command/{}", cmdName), data);
|
||||
}
|
||||
|
||||
void registerSubCommand(const std::string &cmdName, const ForwardCommandHandler &handler) {
|
||||
log::debug("Registered new forward command handler: {}", cmdName);
|
||||
|
||||
ImHexApi::Messaging::impl::getHandlers().insert({ hex::format("command/{}", cmdName), [handler](const std::vector<u8> &eventData){
|
||||
std::string str((const char*) eventData.data(), eventData.size());
|
||||
|
||||
std::vector<std::string> args;
|
||||
|
||||
for (const auto &arg_view : std::views::split(str, '\0')) {
|
||||
std::string arg(arg_view.data(), arg_view.size());
|
||||
args.push_back(arg);
|
||||
}
|
||||
|
||||
handler(args);
|
||||
}});
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ namespace ImGui {
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
#if defined(GL_UNPACK_ROW_LENGTH)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
@@ -48,6 +48,8 @@ namespace ImGui {
|
||||
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
|
||||
}
|
||||
|
||||
Texture::Texture(std::span<const std::byte> bytes, int width, int height) : Texture(reinterpret_cast<const ImU8*>(bytes.data()), bytes.size(), width, height) { }
|
||||
|
||||
Texture::Texture(const char *path) {
|
||||
unsigned char *imageData = stbi_load(path, &this->m_width, &this->m_height, nullptr, 4);
|
||||
if (imageData == nullptr)
|
||||
@@ -788,4 +790,37 @@ namespace ImGui {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DimmedIconToggle(const char *icon, bool *v) {
|
||||
bool pushed = false;
|
||||
bool toggled = false;
|
||||
|
||||
if (*v) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive));
|
||||
pushed = true;
|
||||
}
|
||||
|
||||
if (ImGui::DimmedIconButton(icon, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
*v = !*v;
|
||||
toggled = true;
|
||||
}
|
||||
|
||||
if (pushed)
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
return toggled;
|
||||
}
|
||||
|
||||
void TextOverlay(const char *text, ImVec2 pos) {
|
||||
const auto textSize = ImGui::CalcTextSize(text);
|
||||
const auto textPos = pos - textSize / 2;
|
||||
const auto margin = ImGui::GetStyle().FramePadding * 2;
|
||||
const auto textRect = ImRect(textPos - margin, textPos + textSize + margin);
|
||||
|
||||
auto drawList = ImGui::GetForegroundDrawList();
|
||||
|
||||
drawList->AddRectFilled(textRect.Min, textRect.Max, ImGui::GetColorU32(ImGuiCol_WindowBg) | 0xFF000000);
|
||||
drawList->AddRect(textRect.Min, textRect.Max, ImGui::GetColorU32(ImGuiCol_Border));
|
||||
drawList->AddText(textPos, ImGui::GetColorU32(ImGuiCol_Text), text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
namespace hex::impl {
|
||||
|
||||
std::vector<std::unique_ptr<PopupBase>> PopupBase::s_openPopups;
|
||||
|
||||
[[nodiscard]] std::vector<std::unique_ptr<PopupBase>> &PopupBase::getOpenPopups() {
|
||||
static std::vector<std::unique_ptr<PopupBase>> openPopups;
|
||||
|
||||
return openPopups;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -8,8 +8,12 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
ImFontAtlas *View::s_fontAtlas;
|
||||
ImFontConfig View::s_fontConfig;
|
||||
namespace {
|
||||
|
||||
ImFontAtlas *s_fontAtlas;
|
||||
ImFontConfig s_fontConfig;
|
||||
|
||||
}
|
||||
|
||||
View::View(std::string unlocalizedName) : m_unlocalizedViewName(std::move(unlocalizedName)) { }
|
||||
|
||||
@@ -62,4 +66,10 @@ namespace hex {
|
||||
rightButtonFn();
|
||||
}
|
||||
|
||||
ImFontAtlas *View::getFontAtlas() { return s_fontAtlas; }
|
||||
void View::setFontAtlas(ImFontAtlas *atlas) { s_fontAtlas = atlas; }
|
||||
|
||||
ImFontConfig View::getFontConfig() { return s_fontConfig; }
|
||||
void View::setFontConfig(ImFontConfig config) { s_fontConfig = config; }
|
||||
|
||||
}
|
||||
@@ -9,6 +9,11 @@ add_executable(main ${APPLICATION_TYPE}
|
||||
source/window/macos_window.cpp
|
||||
source/window/linux_window.cpp
|
||||
|
||||
source/messaging/common.cpp
|
||||
source/messaging/linux.cpp
|
||||
source/messaging/macos.cpp
|
||||
source/messaging/win.cpp
|
||||
|
||||
source/init/splash_window.cpp
|
||||
source/init/tasks.cpp
|
||||
|
||||
@@ -23,11 +28,28 @@ set(LIBROMFS_PROJECT_NAME imhex)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/main/libromfs EXCLUDE_FROM_ALL)
|
||||
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set_target_properties(main PROPERTIES
|
||||
if (WIN32)
|
||||
# HACK: `imhex` -> `imhex-gui` and we add a forwarder as `imhex`, so that the user can just run `imhex` and it will start the GUI
|
||||
# Workaround for .NET plugin crashing caused by the console window being freed.
|
||||
set(IMHEX_APPLICATION_NAME "imhex-gui")
|
||||
add_executable(imhex-forwarder
|
||||
source/forwarder/main.cpp
|
||||
${IMHEX_ICON})
|
||||
target_link_libraries(imhex-forwarder PRIVATE libwolv-io ${FMT_LIBRARIES})
|
||||
set_target_properties(imhex-forwarder PROPERTIES
|
||||
OUTPUT_NAME "imhex"
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
else ()
|
||||
set(IMHEX_APPLICATION_NAME "imhex")
|
||||
endif ()
|
||||
|
||||
set_target_properties(main PROPERTIES
|
||||
OUTPUT_NAME ${IMHEX_APPLICATION_NAME}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
namespace hex::crash {
|
||||
|
||||
void setupCrashHandlers();
|
||||
|
||||
}
|
||||
@@ -12,6 +12,14 @@ namespace hex::init {
|
||||
|
||||
using TaskFunction = std::function<bool()>;
|
||||
|
||||
enum FrameResult{ success, failure, wait };
|
||||
|
||||
struct Highlight {
|
||||
ImVec2 start;
|
||||
size_t count;
|
||||
ImColor color;
|
||||
};
|
||||
|
||||
class WindowSplash {
|
||||
public:
|
||||
WindowSplash();
|
||||
@@ -19,6 +27,9 @@ namespace hex::init {
|
||||
|
||||
bool loop();
|
||||
|
||||
FrameResult fullFrame();
|
||||
void startStartupTasks();
|
||||
|
||||
void addStartupTask(const std::string &taskName, const TaskFunction &task, bool async) {
|
||||
this->m_tasks.emplace_back(taskName, task, async);
|
||||
}
|
||||
@@ -27,10 +38,11 @@ namespace hex::init {
|
||||
GLFWwindow *m_window;
|
||||
std::mutex m_progressMutex;
|
||||
std::atomic<float> m_progress = 0;
|
||||
std::string m_currTaskName;
|
||||
std::list<std::string> m_currTaskNames;
|
||||
|
||||
void initGLFW();
|
||||
void initImGui();
|
||||
void initMyself();
|
||||
|
||||
void exitGLFW();
|
||||
void exitImGui();
|
||||
@@ -40,6 +52,12 @@ namespace hex::init {
|
||||
std::vector<std::tuple<std::string, TaskFunction, bool>> m_tasks;
|
||||
|
||||
std::string m_gpuVendor;
|
||||
|
||||
ImGui::Texture splashBackgroundTexture;
|
||||
ImGui::Texture splashTextTexture;
|
||||
std::future<bool> tasksSucceeded;
|
||||
std::array<Highlight, 3> highlights;
|
||||
float progressLerp = 0.0F;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user