Compare commits

..

2 Commits

Author SHA1 Message Date
WerWolv
92b5fd84c2 impr: Simplify tracy integration 2024-06-01 23:57:34 +02:00
WerWolv
3e0bb6d8be feat: Added initial support for tracing function calls and printing exception stack traces 2024-06-01 16:36:36 +02:00
610 changed files with 13286 additions and 89990 deletions

View File

@@ -8,7 +8,7 @@ on:
jobs: jobs:
codeql: codeql:
name: 🐛 CodeQL name: 🐛 CodeQL
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
permissions: permissions:
actions: read actions: read
contents: read contents: read
@@ -49,7 +49,7 @@ jobs:
set -x set -x
mkdir -p build mkdir -p build
cd build cd build
CC=gcc-14 CXX=g++-14 cmake \ CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \ -DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -57,9 +57,8 @@ jobs:
-DCMAKE_C_FLAGS="-fuse-ld=lld" \ -DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \ -DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-G Ninja \
.. ..
ninja install make -j 4 install
- name: 🗯️ Perform CodeQL Analysis - name: 🗯️ Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v2

View File

@@ -6,7 +6,6 @@ on:
- 'master' - 'master'
- 'releases/**' - 'releases/**'
- 'tests/**' - 'tests/**'
- 'feature/**'
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
@@ -19,18 +18,11 @@ jobs:
win: win:
runs-on: windows-2022 runs-on: windows-2022
name: 🪟 Windows MINGW64 name: 🪟 Windows MINGW64
defaults: defaults:
run: run:
shell: msys2 {0} shell: msys2 {0}
env: env:
CCACHE_DIR: "${{ github.workspace }}/.ccache" CCACHE_DIR: "${{ github.workspace }}/.ccache"
permissions:
id-token: write
attestations: write
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -72,7 +64,7 @@ jobs:
cd build cd build
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \ -DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DIMHEX_GENERATE_PACKAGE=ON \ -DIMHEX_GENERATE_PACKAGE=ON \
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \ -DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
@@ -89,62 +81,11 @@ jobs:
run: | run: |
cd build cd build
ninja install ninja install
- name: 🪲 Create PDBs for MSI
run: |
cd build
mkdir cv2pdb
cd cv2pdb
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
unzip cv2pdb-0.52.zip
cd ..
cv2pdb/cv2pdb.exe imhex.exe
cv2pdb/cv2pdb.exe imhex-gui.exe
cv2pdb/cv2pdb.exe libimhex.dll
for plugin in plugins/*.hexplug; do
cv2pdb/cv2pdb.exe $plugin
done
rm -rf cv2pdb
- name: 📦 Bundle MSI
run: |
cd build
cpack cpack
mv ImHex-*.msi ../imhex-${{ env.IMHEX_VERSION }}-Windows-x86_64.msi mv ImHex-*.msi ../imhex-${{env.IMHEX_VERSION}}-Windows-x86_64.msi
echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE echo "ImHex checks for the existence of this file to determine if it is running in portable mode. You should not delete this file" > $PWD/install/PORTABLE
- name: 🪲 Create PDBs for ZIP
run: |
cd build/install
mkdir cv2pdb
cd cv2pdb
wget https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip
unzip cv2pdb-0.52.zip
cd ..
cv2pdb/cv2pdb.exe imhex.exe
cv2pdb/cv2pdb.exe imhex-gui.exe
cv2pdb/cv2pdb.exe libimhex.dll
for plugin in plugins/*.hexplug; do
cv2pdb/cv2pdb.exe $plugin
done
rm -rf cv2pdb
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
imhex-*.msi
- name: ⬆️ Upload Windows Installer - name: ⬆️ Upload Windows Installer
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -166,7 +107,7 @@ jobs:
run: | run: |
set -x set -x
echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md echo "NoGPU version Powered by Mesa 3D : https://fdossena.com/?p=mesa%2Findex.frag" > build/install/MESA.md
curl https://downloads.fdossena.com/geth.php?r=mesa64-latest -L -o mesa.7z curl https://werwolv.net/downloads/mesa/MesaForWindows-x64-latest.7z -L -o mesa.7z
7z e mesa.7z 7z e mesa.7z
mv opengl32.dll build/install mv opengl32.dll build/install
@@ -178,70 +119,9 @@ jobs:
path: | path: |
build/install/* build/install/*
win-plugin-template-test:
runs-on: windows-2022
name: 🧪 Plugin Template Test
defaults:
run:
shell: msys2 {0}
needs: win
env:
IMHEX_SDK_PATH: "${{ github.workspace }}/out/sdk"
steps:
- name: 🧰 Checkout ImHex
uses: actions/checkout@v4
with:
path: imhex
- name: 🟦 Install msys2
uses: msys2/setup-msys2@v2
with:
msystem: mingw64
- name: ⬇️ Install dependencies
run: |
set -x
imhex/dist/get_deps_msys2.sh
- name: 🧰 Checkout ImHex-Plugin-Template
uses: actions/checkout@v4
with:
repository: WerWolv/ImHex-Plugin-Template
submodules: recursive
path: template
- name: ⬇️ Download artifact
uses: actions/download-artifact@v4
with:
name: Windows Portable x86_64
path: out
- name: 🛠️ Build
run: |
set -x
cd template
mkdir -p build
cd build
cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \
-DIMHEX_USE_DEFAULT_BUILD_SETTINGS=ON \
-DUSE_SYSTEM_CAPSTONE=ON \
..
ninja
# MacOS build # MacOS build
macos-x86: macos:
runs-on: macos-13 runs-on: macos-12
permissions:
id-token: write
attestations: write
strategy: strategy:
fail-fast: false fail-fast: false
@@ -252,7 +132,7 @@ jobs:
- suffix: "" - suffix: ""
custom_glfw: false custom_glfw: false
name: 🍎 macOS 13${{ matrix.suffix }} name: 🍎 macOS 12.0${{matrix.suffix}}
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
@@ -272,19 +152,16 @@ jobs:
max-size: 1G max-size: 1G
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
env:
# Make brew not display useless errors
HOMEBREW_TESTS: 1
run: | run: |
brew reinstall python --quiet || true set -x
brew link --overwrite --quiet python 2>/dev/null || true brew reinstall python || brew link --overwrite python
brew bundle --no-lock --quiet --file dist/macOS/Brewfile || true brew bundle --no-lock --file dist/Brewfile
rm -rf /usr/local/Cellar/capstone rm -rf /usr/local/Cellar/capstone
- name: ⬇️ Install classic glfw - name: ⬇️ Install classic glfw
if: ${{! matrix.custom_glfw }} if: ${{! matrix.custom_glfw}}
run: | run: |
brew install --quiet glfw || true brew install glfw
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
@@ -292,7 +169,7 @@ jobs:
dotnet-version: '8.0.100' dotnet-version: '8.0.100'
- name: 🧰 Checkout glfw - name: 🧰 Checkout glfw
if: ${{ matrix.custom_glfw }} if: ${{matrix.custom_glfw}}
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
repository: glfw/glfw repository: glfw/glfw
@@ -300,7 +177,7 @@ jobs:
# GLFW custom build (to allow software rendering) # GLFW custom build (to allow software rendering)
- name: ⬇️ Patch and install custom glfw - name: ⬇️ Patch and install custom glfw
if: ${{ matrix.custom_glfw }} if: ${{matrix.custom_glfw}}
run: | run: |
set -x set -x
cd glfw cd glfw
@@ -310,7 +187,7 @@ jobs:
cd build cd build
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DBUILD_SHARED_LIBS=ON \ -DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
@@ -325,15 +202,14 @@ jobs:
set -x set -x
mkdir -p build mkdir -p build
cd build cd build
CC=$(brew --prefix llvm)/bin/clang \ CC=$(brew --prefix gcc@12)/bin/gcc-12 \
CXX=$(brew --prefix llvm)/bin/clang++ \ CXX=$(brew --prefix gcc@12)/bin/g++-12 \
OBJC=$(brew --prefix llvm)/bin/clang \ OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \ OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \ PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
cmake -G "Ninja" \ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DIMHEX_GENERATE_PACKAGE=ON \ -DIMHEX_GENERATE_PACKAGE=ON \
-DIMHEX_SYSTEM_LIBRARY_PATH="$(brew --prefix llvm)/lib;$(brew --prefix llvm)/lib/unwind;$(brew --prefix llvm)/lib/c++;$(brew --prefix)/lib" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
@@ -361,48 +237,28 @@ jobs:
cd build/install cd build/install
chmod -R 755 ImHex.app/ chmod -R 755 ImHex.app/
- name: 🔫 Kill XProtect
run: |
# See https://github.com/actions/runner-images/issues/7522
echo Killing XProtect...; sudo pkill -9 XProtect >/dev/null || true;
echo Waiting for XProtect process...; while pgrep XProtect; do sleep 3; done;
- name: 📦 Create DMG - name: 📦 Create DMG
run: | run: |
brew install imagemagick set -x
git clone https://github.com/sindresorhus/create-dmg mkdir bundle
cd create-dmg mv build/install/ImHex.app bundle
npm i && npm -g i cd bundle
cd ../build/install ln -s /Applications Applications
for i in $(seq 1 10); do cd ..
create-dmg ImHex.app || true hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS${{matrix.suffix}}-x86_64.dmg
if ls -d *.dmg 1>/dev/null 2>/dev/null; then
break;
fi
done
mv *.dmg ../../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-x86_64.dmg
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
./*.dmg
- name: ⬆️ Upload DMG - name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
if-no-files-found: error if-no-files-found: error
name: macOS DMG${{ matrix.suffix }} x86_64 name: macOS DMG${{matrix.suffix}} x86_64
path: ./*.dmg path: ./*.dmg
macos-arm64: macos-arm64-build:
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
name: 🍎 macOS 13 arm64 name: 🍎 macOS 12.1 arm64
outputs: outputs:
IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }} IMHEX_VERSION: ${{ steps.build.outputs.IMHEX_VERSION }}
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -443,17 +299,11 @@ jobs:
gh actions-cache delete "build-macos-arm64-cache" --confirm || true gh actions-cache delete "build-macos-arm64-cache" --confirm || true
macos-arm64-package: macos-arm64-package:
runs-on: macos-13 runs-on: macos-12
name: 🍎 macOS 13 arm64 Packaging name: 🍎 macOS 12.1 arm64 Packaging
needs: macos-arm64 needs: macos-arm64-build
env: env:
IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }} IMHEX_VERSION: ${{ needs.macos-arm64-build.outputs.IMHEX_VERSION }}
permissions:
id-token: write
attestations: write
steps: steps:
- name: ⬇️ Download artifact - name: ⬇️ Download artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
@@ -480,33 +330,15 @@ jobs:
cd out cd out
chmod -R 755 ImHex.app/ chmod -R 755 ImHex.app/
- name: 🔫 Kill XProtect
run: |
# See https://github.com/actions/runner-images/issues/7522
echo Killing XProtect...; sudo pkill -9 XProtect >/dev/null || true;
echo Waiting for XProtect process...; while pgrep XProtect; do sleep 3; done;
- name: 📦 Create DMG - name: 📦 Create DMG
run: | run: |
brew install imagemagick set -x
git clone https://github.com/sindresorhus/create-dmg mkdir bundle
cd create-dmg mv out/ImHex.app bundle
npm i && npm -g i cd bundle
cd ../out ln -s /Applications Applications
for i in $(seq 1 10); do cd ..
create-dmg ImHex.app || true hdiutil create -volname "ImHex" -srcfolder bundle -ov -format UDZO imhex-${{env.IMHEX_VERSION}}-macOS-arm64.dmg
if ls -d *.dmg 1>/dev/null 2>/dev/null; then
break;
fi
done
mv *.dmg ../imhex-${{ env.IMHEX_VERSION }}-macOS${{ matrix.suffix }}-arm64.dmg
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
./*.dmg
- name: ⬆️ Upload DMG - name: ⬆️ Upload DMG
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -521,20 +353,16 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- release_num: "24.04" - release_num: 22.04
- release_num: "24.10" - release_num: 23.04
name: 🐧 Ubuntu ${{ matrix.release_num }} name: 🐧 Ubuntu ${{ matrix.release_num }}
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
container: container:
image: "ubuntu:${{ matrix.release_num }}" image: "ubuntu:${{ matrix.release_num }}"
options: --privileged options: --privileged
permissions:
id-token: write
attestations: write
steps: steps:
- name: ⬇️ Install setup dependencies - name: ⬇️ Install setup dependencies
run: apt update && apt install -y git curl run: apt update && apt install -y git curl
@@ -547,8 +375,8 @@ jobs:
- name: 📜 Setup ccache - name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1 uses: hendrikmuhs/ccache-action@v1
with: with:
key: Ubuntu-${{ matrix.release_num }}-ccache-${{ github.run_id }} key: Ubuntu-${{matrix.release_num}}-ccache-${{ github.run_id }}
restore-keys: Ubuntu-${{ matrix.release_num }}-ccache restore-keys: Ubuntu-${{matrix.release_num}}-ccache
max-size: 1G max-size: 1G
- name: ⬇️ Install dependencies - name: ⬇️ Install dependencies
@@ -556,6 +384,11 @@ jobs:
apt update apt update
bash dist/get_deps_debian.sh bash dist/get_deps_debian.sh
apt install software-properties-common -y
add-apt-repository ppa:ubuntu-toolchain-r/test -y
apt update
apt install -y gcc-13 g++-13
- name: ⬇️ Install .NET - name: ⬇️ Install .NET
uses: actions/setup-dotnet@v4 uses: actions/setup-dotnet@v4
with: with:
@@ -569,8 +402,8 @@ jobs:
git config --global --add safe.directory '*' git config --global --add safe.directory '*'
mkdir -p build mkdir -p build
cd build cd build
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \ CC=gcc-13 CXX=g++-13 cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX="/usr" \ -DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
@@ -592,15 +425,8 @@ jobs:
- name: 📦 Bundle DEB - name: 📦 Bundle DEB
run: | run: |
cp -r build/DEBIAN build/DebDir cp -r build/DEBIAN build/DebDir
dpkg-deb -Zzstd --build build/DebDir dpkg-deb -Zgzip --build build/DebDir
mv build/DebDir.deb imhex-${{ env.IMHEX_VERSION }}-Ubuntu-${{ matrix.release_num }}-x86_64.deb mv build/DebDir.deb imhex-${{env.IMHEX_VERSION}}-Ubuntu-${{ matrix.release_num }}-x86_64.deb
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
./*.deb
- name: ⬆️ Upload DEB - name: ⬆️ Upload DEB
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -611,26 +437,8 @@ jobs:
# AppImage build # AppImage build
appimage: appimage:
strategy: runs-on: ubuntu-22.04
fail-fast: false name: ⬇️ AppImage
matrix:
include:
- architecture: "x86_64"
architecture_package: "amd64"
architecture_appimage_builder: "x86_64"
image: ubuntu-24.04
- architecture: "arm64"
architecture_package: "arm64"
architecture_appimage_builder: "aarch64"
image: ubuntu-24.04-arm
runs-on: ${{ matrix.image }}
name: ⬇️ AppImage ${{ matrix.architecture }}
permissions:
id-token: write
attestations: write
steps: steps:
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -652,45 +460,32 @@ jobs:
- name: 🛠️ Build using docker - name: 🛠️ Build using docker
run: | run: |
docker buildx build . -f dist/AppImage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \ docker buildx build . -f dist/appimage/Dockerfile --progress=plain --build-arg "BUILD_TYPE=$BUILD_TYPE" \
--build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" \ --build-arg "GIT_COMMIT_HASH=$GITHUB_SHA" --build-arg "GIT_BRANCH=${GITHUB_REF##*/}" --output out
--build-arg "ARCHITECTURE_PACKAGE=${{ matrix.architecture_package }}" --build-arg "ARCHITECTURE_FILE_NAME=${{ matrix.architecture }}" --build-arg "ARCHITECTURE_APPIMAGE_BUILDER=${{ matrix.architecture_appimage_builder }}" \
--output out
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
out/*.AppImage
out/*.AppImage.zsync
- name: ⬆️ Upload AppImage - name: ⬆️ Upload AppImage
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
if-no-files-found: error if-no-files-found: error
name: Linux AppImage ${{ matrix.architecture }} name: Linux AppImage x86_64
path: 'out/*.AppImage' path: 'out/*.AppImage'
- name: ⬆️ Upload AppImage zsync - name: ⬆️ Upload AppImage zsync
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
if-no-files-found: error if-no-files-found: error
name: Linux AppImage zsync ${{ matrix.architecture }} name: Linux AppImage zsync x86_64
path: 'out/*.AppImage.zsync' path: 'out/*.AppImage.zsync'
# ArchLinux build # ArchLinux build
archlinux-build: archlinux-build:
name: 🐧 ArchLinux name: 🐧 ArchLinux
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
container: container:
image: archlinux:base-devel image: archlinux:base-devel
permissions:
id-token: write
attestations: write
steps: steps:
- name: ⬇️ Update all packages - name: ⬇️ Update all packages
run: | run: |
@@ -728,7 +523,7 @@ jobs:
mkdir -p build mkdir -p build
cd build cd build
CC=gcc CXX=g++ cmake -G "Ninja" \ CC=gcc CXX=g++ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX="/usr" \ -DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
@@ -753,7 +548,7 @@ jobs:
- name: ✒️ Prepare PKGBUILD - name: ✒️ Prepare PKGBUILD
run: | run: |
cp dist/Arch/PKGBUILD build cp dist/Arch/PKGBUILD build
sed -i 's/%version%/${{ env.IMHEX_VERSION }}/g' build/PKGBUILD sed -i 's/%version%/${{env.IMHEX_VERSION}}/g' build/PKGBUILD
# makepkg doesn't want to run as root, so I had to chmod 777 all over # makepkg doesn't want to run as root, so I had to chmod 777 all over
- name: 📦 Package ArchLinux .pkg.tar.zst - name: 📦 Package ArchLinux .pkg.tar.zst
@@ -763,23 +558,16 @@ jobs:
# the name is a small trick to make makepkg recognize it as the source # the name is a small trick to make makepkg recognize it as the source
# else, it would try to download the file from the release # else, it would try to download the file from the release
tar -cvf imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst -C installDir . tar -cvf imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst -C installDir .
chmod -R 777 . chmod -R 777 .
sudo -u nobody makepkg sudo -u nobody makepkg
# Replace the old file # Replace the old file
rm imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst rm imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
rm *imhex-bin-debug* # rm debug package which is created for some reason rm *imhex-bin-debug* # rm debug package which is created for some reason
mv *.pkg.tar.zst imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst mv *.pkg.tar.zst imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst
- name: ⬆️ Upload imhex-archlinux.pkg.tar.zst - name: ⬆️ Upload imhex-archlinux.pkg.tar.zst
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -787,7 +575,7 @@ jobs:
if-no-files-found: error if-no-files-found: error
name: ArchLinux .pkg.tar.zst x86_64 name: ArchLinux .pkg.tar.zst x86_64
path: | path: |
build/imhex-${{ env.IMHEX_VERSION }}-ArchLinux-x86_64.pkg.tar.zst build/imhex-${{env.IMHEX_VERSION}}-ArchLinux-x86_64.pkg.tar.zst
# RPM distro builds # RPM distro builds
rpm-build: rpm-build:
@@ -800,45 +588,28 @@ jobs:
release_num: rawhide release_num: rawhide
mock_config: fedora-rawhide mock_config: fedora-rawhide
- name: Fedora - name: Fedora
mock_release: f41 mock_release: f39
release_num: 41 release_num: 39
mock_config: fedora-41 mock_config: fedora-39
- name: Fedora - name: Fedora
mock_release: f40 mock_release: f38
release_num: 40 release_num: 38
mock_config: fedora-40 mock_config: fedora-38
- name: RHEL-AlmaLinux - name: RHEL-AlmaLinux
mock_release: epel9 mock_release: epel9
release_num: 9 release_num: 9
mock_config: "alma+epel-9" mock_config: "alma+epel-9"
name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }} name: 🐧 ${{ matrix.name }} ${{ matrix.release_num }}
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
container: container:
image: "almalinux:9" image: "fedora:latest"
options: --privileged --pid=host --security-opt apparmor=unconfined options: --privileged
permissions:
id-token: write
attestations: write
steps: steps:
# This, together with the `--pid=host --security-opt apparmor=unconfined` docker options is required to allow - name: ⬇️ Install git-core
# fedpkg to work inside a Docker container running on Ubuntu again. run: dnf install --disablerepo="*" --enablerepo="fedora" git-core -y
# GitHub seems to have enabled AppArmor on their Ubuntu CI runners which limits Docker in ways that cause
# programs inside it to fail.
# Without this, fedpkg will throw the unhelpful error message 'Insufficient Rights'
# This step uses nsenter to execute commands on the host that disable AppArmor entirely.
- name: 🛡️ Disable AppArmor on Host
run: |
nsenter -t 1 -m -u -n -i sudo systemctl disable --now apparmor.service
nsenter -t 1 -m -u -n -i sudo aa-teardown || true
nsenter -t 1 -m -u -n -i sudo sysctl --write kernel.apparmor_restrict_unprivileged_unconfined=0
nsenter -t 1 -m -u -n -i sudo sysctl --write kernel.apparmor_restrict_unprivileged_userns=0
- name: ⬇️ Install git-core and EPEL repo
run: dnf install git-core epel-release -y
- name: 🧰 Checkout - name: 🧰 Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -857,8 +628,8 @@ jobs:
- name: ⬇️ Update all packages and install dependencies - name: ⬇️ Update all packages and install dependencies
run: | run: |
set -x set -x
dnf upgrade -y dnf upgrade --disablerepo="*" --enablerepo="fedora,updates" -y
dnf install -y \ dnf install --disablerepo="*" --enablerepo="fedora,updates" -y \
fedpkg \ fedpkg \
ccache ccache
@@ -884,16 +655,16 @@ jobs:
- name: ✒️ Modify spec file - name: ✒️ Modify spec file
run: | run: |
sed -i \ sed -i \
-e 's/Version: VERSION$/Version: ${{ env.IMHEX_VERSION }}/g' \ -e 's/Version: VERSION$/Version: ${{env.IMHEX_VERSION}}/g' \
-e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \ -e 's/IMHEX_OFFLINE_BUILD=ON/IMHEX_OFFLINE_BUILD=OFF/g' \
-e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \ -e '/IMHEX_OFFLINE_BUILD=OFF/a -D IMHEX_PATTERNS_PULL_MASTER=ON \\' \
-e '/BuildRequires: cmake/a BuildRequires: git-core' \ -e '/BuildRequires: cmake/a BuildRequires: git-core' \
-e '/%files/a %{_datadir}/%{name}/' \ -e '/%files/a %{_datadir}/%{name}/' \
$GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
- name: 📜 Fix ccache on EL9 - name: 📜 Fix ccache on EL9
if: matrix.mock_release == 'epel9' if: matrix.mock_release == 'epel9'
run: sed -i '/\. \/opt\/rh\/gcc-toolset-14\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec run: sed -i '/\. \/opt\/rh\/gcc-toolset-12\/enable/a PATH=/usr/lib64/ccache:$PATH' $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec
- name: 🟩 Copy spec file to build root - name: 🟩 Copy spec file to build root
run: mv $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/imhex.spec run: mv $GITHUB_WORKSPACE/ImHex/dist/rpm/imhex.spec $GITHUB_WORKSPACE/imhex.spec
@@ -915,15 +686,8 @@ jobs:
- name: 🟩 Move and rename finished RPM - name: 🟩 Move and rename finished RPM
run: | run: |
mv $GITHUB_WORKSPACE/results_imhex/${{ env.IMHEX_VERSION }}/*/imhex-${{ env.IMHEX_VERSION }}-0.*.x86_64.rpm \ mv $GITHUB_WORKSPACE/results_imhex/${{env.IMHEX_VERSION}}/*/imhex-${{env.IMHEX_VERSION}}-0.*.x86_64.rpm \
$GITHUB_WORKSPACE/imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm $GITHUB_WORKSPACE/imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
- name: 🗝️ Generate build provenance attestations
uses: actions/attest-build-provenance@v2
if: github.event.pull_request.head.repo.full_name == github.repository
with:
subject-path: |
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm
- name: ⬆️ Upload RPM - name: ⬆️ Upload RPM
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -931,86 +695,4 @@ jobs:
if-no-files-found: error if-no-files-found: error
name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64 name: ${{ matrix.name }} ${{ matrix.release_num }} RPM x86_64
path: | path: |
imhex-${{ env.IMHEX_VERSION }}-${{ matrix.name }}-${{ matrix.release_num }}-x86_64.rpm imhex-${{env.IMHEX_VERSION}}-${{matrix.name}}-${{matrix.release_num}}-x86_64.rpm
webassembly-build:
runs-on: ubuntu-24.04
name: 🌍 Web
permissions:
pages: write
id-token: write
actions: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v4
with:
path: cache
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2
with:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
- name: 🔨 Fix permissions
run: |
chmod -c -R +rX "out/"
- name: ⬆️ Upload artifacts
uses: actions/upload-pages-artifact@v3
with:
path: out/
- name: 🔨 Copy necessary files
run: |
cp dist/web/serve.py out/start_imhex_web.py
- name: ⬆️ Upload package
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: ImHex Web
path: out/*
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
- name: 🗑️ Delete old cache
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
gh extension install actions/gh-actions-cache || true
gh actions-cache delete "build-web-cache" --confirm || true
webassembly-deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
id-token: write
actions: write
name: 📃 Deploy to GitHub Pages
runs-on: ubuntu-24.04
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
needs: webassembly-build
steps:
- name: 🌍 Deploy WebAssembly Build to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
- name: 🗑️ Delete artifact
uses: geekyeggo/delete-artifact@v5
with:
name: github-pages

80
.github/workflows/build_web.yml vendored Normal file
View File

@@ -0,0 +1,80 @@
name: Build for the web
on:
push:
branches:
- 'master'
- 'releases/**'
- 'tests/**'
pull_request:
workflow_dispatch:
env:
BUILD_TYPE: Release
permissions:
pages: write
id-token: write
actions: write
jobs:
build:
runs-on: ubuntu-22.04
name: 🌍 WebAssembly
steps:
- name: 🧰 Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📁 Restore docker /cache
uses: actions/cache@v4
with:
path: cache
key: web-cache-${{ hashFiles('**/CMakeLists.txt') }}
- name: 🐳 Inject /cache into docker
uses: reproducible-containers/buildkit-cache-dance@v2
with:
cache-source: cache
cache-target: /cache
- name: 🛠️ Build using docker
run: |
docker buildx build . -f dist/web/Dockerfile --progress=plain --build-arg 'JOBS=4' --output out --target raw
- name: 🔨 Fix permissions
run: |
chmod -c -R +rX "out/"
- name: ⬆️ Upload artifacts
uses: actions/upload-pages-artifact@v2
with:
path: out/
# See https://github.com/actions/cache/issues/342#issuecomment-1711054115
- name: 🗑️ Delete old cache
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
run: |
gh extension install actions/gh-actions-cache
gh actions-cache delete "build-web-cache" --confirm
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
name: 📃 Deploy to GitHub Pages
runs-on: ubuntu-latest
if: ${{ github.ref == 'refs/heads/master' && github.event.repository.fork == false }}
needs: build
steps:
- name: 🌍 Deploy
id: deployment
uses: actions/deploy-pages@v2

View File

@@ -10,7 +10,7 @@ on:
jobs: jobs:
release-update-repos: release-update-repos:
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
name: Release Update Repos name: Release Update Repos
steps: steps:
@@ -63,7 +63,7 @@ jobs:
token: ${{ secrets.RELEASE_TOKEN }} token: ${{ secrets.RELEASE_TOKEN }}
release-upload-artifacts: release-upload-artifacts:
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
name: Release Upload Artifacts name: Release Upload Artifacts
steps: steps:
@@ -90,7 +90,7 @@ jobs:
run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex run: tar --exclude-vcs -czvf Full.Sources.tar.gz ImHex
- name: ⬇️ Download artifacts from latest workflow - name: ⬇️ Download artifacts from latest workflow
uses: dawidd6/action-download-artifact@v6 uses: dawidd6/action-download-artifact@v3
with: with:
github_token: ${{secrets.GITHUB_TOKEN}} github_token: ${{secrets.GITHUB_TOKEN}}
workflow: build.yml workflow: build.yml
@@ -117,7 +117,6 @@ jobs:
run: | run: |
mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip mv "Windows Portable x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-x86_64.zip
mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip mv "Windows Portable NoGPU x86_64.zip" imhex-${{ env.IMHEX_VERSION }}-Windows-Portable-NoGPU-x86_64.zip
mv "ImHex Web.zip" imhex-${{ env.IMHEX_VERSION }}-web.zip
- name: ⬆️ Upload everything to release - name: ⬆️ Upload everything to release
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981 uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
@@ -148,7 +147,7 @@ jobs:
commit_email: itrooz@protonmail.com commit_email: itrooz@protonmail.com
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Bump to version ${{ env.IMHEX_VERSION }} commit_message: Bump to version ${{ env.IMHEX_VERSION }}
ssh_keyscan_types: rsa,ecdsa,ed25519 ssh_keyscan_types: rsa,dsa,ecdsa,ed25519
release-update-winget: release-update-winget:
name: Release update winget package name: Release update winget package

View File

@@ -1,30 +0,0 @@
name: Close inactive issues
on:
schedule:
- cron: "30 1 * * 0"
workflow_dispatch:
jobs:
close-issues:
runs-on: ubuntu-24.04
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v5
with:
operations-per-run: '200'
ascending: true
days-before-issue-stale: 334
days-before-issue-close: 30
stale-issue-label: "stale"
stale-issue-message: |
This issue is marked stale as it has been open for 11 months without activity.
Please try the latest ImHex version. (Avaiable here: https://imhex.download/ for release and https://imhex.download/#nightly for development version)
If the issue persists on the latest version, please make a comment on this issue again
Without response, this issue will be closed in one month.
close-issue-message: ""
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -6,7 +6,6 @@ on:
- 'master' - 'master'
- 'releases/**' - 'releases/**'
- 'tests/**' - 'tests/**'
- 'feature/**'
pull_request: pull_request:
branches: branches:
- 'master' - 'master'
@@ -16,7 +15,7 @@ on:
jobs: jobs:
tests: tests:
name: 🧪 Unit Tests name: 🧪 Unit Tests
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
permissions: permissions:
actions: read actions: read
contents: read contents: read
@@ -39,25 +38,23 @@ jobs:
run: | run: |
sudo apt update sudo apt update
sudo bash dist/get_deps_debian.sh sudo bash dist/get_deps_debian.sh
sudo apt install gcovr -y
- name: 🛠️ Build - name: 🛠️ Build
run: | run: |
set -x set -x
mkdir -p build mkdir -p build
cd build cd build
CC=gcc-14 CXX=g++-14 cmake \ CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_BUILD_TYPE=Debug \
-DIMHEX_ENABLE_UNIT_TESTS=ON \ -DIMHEX_ENABLE_UNIT_TESTS=ON \
-DIMHEX_ENABLE_PLUGIN_TESTS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \ -DCMAKE_C_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \ -DCMAKE_CXX_FLAGS="-fuse-ld=lld -fsanitize=address,leak,undefined -fno-sanitize-recover=all --coverage" \
-DIMHEX_OFFLINE_BUILD=ON \ -DIMHEX_OFFLINE_BUILD=ON \
-G Ninja \
.. ..
ninja unit_tests make -j4 unit_tests
ninja imhex_all
- name: 🧪 Perform plcli Integration Tests - name: 🧪 Perform plcli Integration Tests
run: | run: |
@@ -70,24 +67,16 @@ jobs:
ctest --output-on-failure ctest --output-on-failure
# Generate report from all gcov .gcda files # Generate report from all gcov .gcda files
#- name: 🧪 Generate coverage report - name: 🧪 Generate coverage report
# run: | run: |
# sudo apt install python3-pip python3-venv gcovr --gcov-executable /usr/bin/gcov-12 -r . build --xml coverage_report.xml --verbose
# python3 -m venv venv
# . venv/bin/activate - name: Upload coverage reports to Codecov
# pip3 install gcovr uses: codecov/codecov-action@v4
# cd build with:
# gcovr --gcov-executable /usr/bin/gcov-14 --exclude '.*/yara_rules/' --exclude '.*/third_party/' --exclude '.*/external/' --root .. --xml coverage_report.xml --verbose --gcov-ignore-errors all fail_ci_if_error: true
# token: ${{ secrets.CODECOV_TOKEN }}
#- name: Upload coverage reports to Codecov file: coverage_report.xml
# env:
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
# if: ${{ env.CODECOV_TOKEN }}
# uses: codecov/codecov-action@v4
# with:
# fail_ci_if_error: true
# token: ${{ secrets.CODECOV_TOKEN }}
# file: build/coverage_report.xml
langs: langs:
name: 🧪 Langs name: 🧪 Langs

3
.gitignore vendored
View File

@@ -6,7 +6,6 @@ cmake-build-*/
build*/ build*/
local/ local/
venv/ venv/
.cache/
*.mgc *.mgc
*.kdev4 *.kdev4
@@ -14,5 +13,3 @@ imgui.ini
.DS_Store .DS_Store
CMakeUserPresets.json CMakeUserPresets.json
Brewfile.lock.json Brewfile.lock.json
.vs/

3
.gitmodules vendored
View File

@@ -44,6 +44,3 @@
[submodule "lib/third_party/HashLibPlus"] [submodule "lib/third_party/HashLibPlus"]
path = lib/third_party/HashLibPlus path = lib/third_party/HashLibPlus
url = https://github.com/WerWolv/HashLibPlus url = https://github.com/WerWolv/HashLibPlus
[submodule "lib/external/disassembler"]
path = lib/external/disassembler
url = https://github.com/WerWolv/Disassembler

View File

@@ -21,7 +21,7 @@ option(IMHEX_REPLACE_DWARF_WITH_PDB "Remove DWARF information from binaries
option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF) option(IMHEX_ENABLE_STD_ASSERTS "Enable debug asserts in the C++ std library. (Breaks Plugin ABI!)" OFF)
option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" OFF) option(IMHEX_ENABLE_UNIT_TESTS "Enable building unit tests" OFF)
option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF) option(IMHEX_ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON ) option(IMHEX_COMPRESS_DEBUG_INFO "Compress debug information" ON )
set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}") set(IMHEX_BASE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules") set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
@@ -32,17 +32,16 @@ include("${IMHEX_BASE_FOLDER}/cmake/ide_helpers.cmake")
# Basic compiler and cmake configurations # Basic compiler and cmake configurations
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON) set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake") include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
# Setup project # Setup project
loadVersion(IMHEX_VERSION IMHEX_VERSION_PLAIN) loadVersion(IMHEX_VERSION)
setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION}) setVariableInParent(IMHEX_VERSION ${IMHEX_VERSION})
configureCMake() configureCMake()
project(imhex project(imhex
LANGUAGES C CXX LANGUAGES C CXX
VERSION ${IMHEX_VERSION_PLAIN} VERSION ${IMHEX_VERSION}
DESCRIPTION "The ImHex Hex Editor" DESCRIPTION "The ImHex Hex Editor"
HOMEPAGE_URL "https://imhex.werwolv.net" HOMEPAGE_URL "https://imhex.werwolv.net"
) )
@@ -70,21 +69,20 @@ addBundledLibraries()
add_subdirectory(lib/libimhex) add_subdirectory(lib/libimhex)
add_subdirectory(main) add_subdirectory(main)
addPluginDirectories() addPluginDirectories()
add_subdirectory(lib/trace)
# Add unit tests # Add unit tests
if (IMHEX_ENABLE_UNIT_TESTS) if (IMHEX_ENABLE_UNIT_TESTS)
if (NOT TARGET unit_tests) enable_testing()
enable_testing() add_subdirectory(tests EXCLUDE_FROM_ALL)
add_custom_target(unit_tests)
add_subdirectory(tests EXCLUDE_FROM_ALL)
endif ()
endif () endif ()
# Configure more resources that will be added to the install package # Configure more resources that will be added to the install package
generatePDBs()
generateSDKDirectory() generateSDKDirectory()
# Handle package generation # Handle package generation
createPackage() createPackage()
# Accommodate IDEs with FOLDER support # Accomodate IDEs with FOLDER support
tweakTargetsForIDESupport() tweakTargetsForIDESupport()

View File

@@ -45,19 +45,6 @@
"IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER": "ON" "IMHEX_IDE_HELPERS_OVERRIDE_XCODE_COMPILER": "ON"
} }
},
{
"name": "vs2022",
"displayName": "Visual Studio 2022",
"generator": "Visual Studio 17 2022",
"binaryDir": "${sourceDir}/build/${presetName}",
"architecture": {
"strategy": "set",
"value": "x64"
},
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
} }
], ],
"buildPresets": [ "buildPresets": [

View File

@@ -27,11 +27,6 @@ chmod +x imhex-*.AppImage
./imhex-*.AppImage ./imhex-*.AppImage
``` ```
If you're experiencing glib / libgtk assertion failures, you might need to setup your `XDG_DATA_DIRS` env var correctly. In this case, run the following command before executing the AppImage. (See issue [ImHex/#2038](https://github.com/WerWolv/ImHex/issues/2038))
```bash
export XDG_DATA_DIRS="/usr/local/share:/usr/share"
```
#### Flatpak #### Flatpak
To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command: To install the Flatpak, make sure you have the Flathub repository added to your system. Then simply run the following command:

View File

@@ -1,16 +1,13 @@
<a href="https://imhex.werwolv.net"> <a href="https://imhex.werwolv.net">
<h1 align="center"> <h1 align="center">
<picture> <picture>
<img height="300px" style="margin: 0; padding: 0" src="./resources/dist/common/logo/ImHexLogoSVGBG.svg"> <img height="300px" src="./resources/dist/common/logo/ImHexLogoSVGBG.svg">
</picture> </picture>
</h1> </h1>
</a> </a>
<p align="center"> <p align="center">A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</p>
A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.
<br>
<a href="https://itinerarium.github.io/phoneme-synthesis/?w=/'ˈɪmhɛks/"><strong>/ˈɪmhɛks/</strong></a>
</p>
<p align="center"> <p align="center">
<a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild"><img alt="'Build' workflow Status" src="https://img.shields.io/github/actions/workflow/status/WerWolv/ImHex/build.yml?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions&branch=master"></a> <a title="'Build' workflow Status" href="https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild"><img alt="'Build' workflow Status" src="https://img.shields.io/github/actions/workflow/status/WerWolv/ImHex/build.yml?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions&branch=master"></a>
<a title="Discord Server" href="https://discord.gg/X63jZ36xBY"><img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&logoColor=fff&style=for-the-badge"></a> <a title="Discord Server" href="https://discord.gg/X63jZ36xBY"><img alt="Discord Server" src="https://img.shields.io/discord/789833418631675954?label=Discord&logo=Discord&logoColor=fff&style=for-the-badge"></a>
@@ -38,8 +35,8 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
</p> </p>
## Screenshots ## Screenshots
![Hex editor, patterns and data information](https://github.com/user-attachments/assets/902a7c4c-410d-490f-999e-14c856fec027) ![Hex editor, patterns and data information](https://github.com/WerWolv/ImHex/assets/10835354/4f358238-2d27-41aa-9015-a2c6cc3708cf)
![Bookmarks, data information, find view and data processor](https://github.com/user-attachments/assets/58eefa1f-31c9-4bb8-a1c1-8cdd8ddbd29f) ![Bookmarks, disassembler and data processor](https://github.com/WerWolv/ImHex/assets/10835354/183bc2cc-2439-4ded-b4c5-b140e19fc92f)
<details> <details>
<summary><strong>More Screenshots</strong></summary> <summary><strong>More Screenshots</strong></summary>
@@ -314,26 +311,22 @@ To use ImHex, the following minimal system requirements need to be met.
> ImHex requires a GPU with OpenGL 3.0 support in general. > ImHex requires a GPU with OpenGL 3.0 support in general.
> There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions. > There are releases available (with the `-NoGPU` suffix) that are software rendered and don't require a GPU, however these can be a lot slower than the GPU accelerated versions.
> >
> If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one. > If possible at all, make ImHex use the dedicated GPU on your system instead of the integrated one (especially Intel HD GPUs are known to cause issues).
> ImHex will usually run fine with integrated GPUs as well but certain Intel HD GPU drivers on Windows are known to cause graphical artifacts.
- **OS**: - **OS**:
- **Windows**: Windows 7 or higher (Windows 10/11 recommended) - **Windows**: Windows 7 or higher (Windows 10/11 recommended)
- **macOS**: macOS 13 (Ventura) or higher, - **macOS**: macOS 11 (Big Sur) or higher,
- Lower versions should still work too, but you'll need to compile ImHex yourself. The release binaries will NOT work.
- The macOS build is not signed and will require you to manually allow them in the Security & Privacy settings.
- **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases. - **Linux**: "Modern" Linux. The following distributions have official releases available. Other distros are supported through the AppImage and Flatpak releases.
- Ubuntu and Debian - Ubuntu 22.04/23.04
- Fedora - Fedora 36/37
- RHEL/AlmaLinux - RHEL/AlmaLinux 9
- Arch Linux - Arch Linux
- Basically any other distro will work as well when compiling ImHex from sources. - **CPU**: x86_64 (64 Bit)
- **CPU**: Officially supported are x86_64 and ARM64, though any Little Endian 64 bit CPU should work.
- **GPU**: OpenGL 3.0 or higher - **GPU**: OpenGL 3.0 or higher
- Integrated Intel HD iGPUs are supported, however certain drivers are known to cause various graphical artifacts, especially on Windows. Use at your own risk. - Intel HD drivers are really buggy and often cause graphic artifacts
- In case you don't have a GPU available, there are software rendered releases available for Windows and macOS - In case you don't have a GPU available, there are software rendered releases available for Windows and macOS
- **RAM**: ~150MiB, more is required for more complex analysis - **RAM**: 256MB, more may be required for more complicated analysis
- **Storage**: 150MiB - **Storage**: 100MB
## Installing ## Installing
@@ -342,10 +335,8 @@ Information on how to install ImHex can be found in the [Install](/INSTALL.md) g
## Compiling ## Compiling
To compile ImHex on any platform, GCC (or Clang) is required with a version that supports C++23 or higher. To compile ImHex on any platform, GCC (or Clang) is required with a version that supports C++23 or higher.
Windows and Linux releases are being built using latest available GCC. On macOS, Clang is also required to compile some ObjC code.
MacOS releases are being built using latest available LLVM Clang. All releases are being built using latest available GCC.
Important to note is, the MSVC and AppleClang compilers are both **NOT** supported since they're both generally severely outdated and lack features GCC and LLVM Clang have.
> [!NOTE] > [!NOTE]
> Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option. > Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.

View File

@@ -1 +1 @@
1.37.0.WIP 1.33.0

View File

@@ -1,73 +1,3 @@
# 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)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
if (POLICY CMP0177)
set(CMAKE_POLICY_DEFAULT_CMP0177 OLD)
cmake_policy(SET CMP0177 OLD)
endif()
function(getTarget target type)
get_target_property(IMPORTED_TARGET ${target} IMPORTED)
if (IMPORTED_TARGET)
set(${type} INTERFACE PARENT_SCOPE)
else()
set(${type} PRIVATE PARENT_SCOPE)
endif()
endfunction()
function(addCFlag)
if (ARGC EQUAL 1)
add_compile_options($<$<COMPILE_LANGUAGE:C>:${ARGV0}>)
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:C>:${ARGV0}>)
endif()
endfunction()
function(addCXXFlag)
if (ARGC EQUAL 1)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${ARGV0}>)
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:CXX>:${ARGV0}>)
endif()
endfunction()
function(addObjCFlag)
if (ARGC EQUAL 1)
add_compile_options($<$<COMPILE_LANGUAGE:OBJC>:${ARGV0}>)
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_compile_options(${ARGV1} ${TYPE} $<$<COMPILE_LANGUAGE:OBJC>:${ARGV0}>)
endif()
endfunction()
function(addLinkerFlag)
if (ARGC EQUAL 1)
add_link_options(${ARGV0})
elseif (ARGC EQUAL 2)
getTarget(${ARGV1} TYPE)
target_link_options(${ARGV1} ${TYPE} ${ARGV0})
endif()
endfunction()
function(addCCXXFlag)
addCFlag(${ARGV0} ${ARGV1})
addCXXFlag(${ARGV0} ${ARGV1})
endfunction()
function(addCommonFlag)
addCFlag(${ARGV0} ${ARGV1})
addCXXFlag(${ARGV0} ${ARGV1})
addObjCFlag(${ARGV0} ${ARGV1})
endfunction()
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
include(FetchContent) include(FetchContent)
if(IMHEX_STRIP_RELEASE) if(IMHEX_STRIP_RELEASE)
@@ -129,9 +59,6 @@ macro(detectOS)
set(CMAKE_INSTALL_LIBDIR ".") set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins") set(PLUGINS_INSTALL_LOCATION "plugins")
add_compile_definitions(WIN32_LEAN_AND_MEAN) add_compile_definitions(WIN32_LEAN_AND_MEAN)
add_compile_definitions(NOMINMAX)
add_compile_definitions(UNICODE)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
elseif (APPLE) elseif (APPLE)
add_compile_definitions(OS_MACOS) add_compile_definitions(OS_MACOS)
set(CMAKE_INSTALL_BINDIR ".") set(CMAKE_INSTALL_BINDIR ".")
@@ -182,7 +109,7 @@ macro(configurePackingResources)
set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico") set(CPACK_WIX_PRODUCT_ICON "${PROJECT_SOURCE_DIR}/resources/dist/windows/icon.ico")
set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png") set(CPACK_WIX_UI_BANNER "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_banner.png")
set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png") set(CPACK_WIX_UI_DIALOG "${PROJECT_SOURCE_DIR}/resources/dist/windows/wix_dialog.png")
set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW;ru-RU") set(CPACK_WIX_CULTURES "en-US;de-DE;ja-JP;it-IT;pt-BR;zh-CN;zh-TW")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex") set(CPACK_PACKAGE_INSTALL_DIRECTORY "ImHex")
set_property(INSTALL "$<TARGET_FILE_NAME:main>" set_property(INSTALL "$<TARGET_FILE_NAME:main>"
PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex" PROPERTY CPACK_START_MENU_SHORTCUTS "ImHex"
@@ -297,8 +224,7 @@ macro(createPackage)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dist/imhex.mime.xml DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mime/packages RENAME imhex.xml) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon.svg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.svg)
downloadImHexPatternsFiles("./share/imhex") downloadImHexPatternsFiles("./share/imhex")
# install AppStream file # install AppStream file
@@ -312,7 +238,6 @@ macro(createPackage)
if (APPLE) if (APPLE)
if (IMHEX_GENERATE_PACKAGE) if (IMHEX_GENERATE_PACKAGE)
set(EXTRA_BUNDLE_LIBRARY_PATHS ${EXTRA_BUNDLE_LIBRARY_PATHS} "${IMHEX_SYSTEM_LIBRARY_PATH}")
include(PostprocessBundle) include(PostprocessBundle)
set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION}) set_target_properties(libimhex PROPERTIES SOVERSION ${IMHEX_VERSION})
@@ -343,7 +268,7 @@ macro(createPackage)
find_program(CODESIGN_PATH codesign) find_program(CODESIGN_PATH codesign)
if (CODESIGN_PATH) if (CODESIGN_PATH)
install(CODE "message(STATUS \"Signing bundle '${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}'...\")") install(CODE "message(STATUS \"Signing bundle '${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}'...\")")
install(CODE "execute_process(COMMAND ${CODESIGN_PATH} --force --deep --entitlements ${CMAKE_SOURCE_DIR}/resources/macos/Entitlements.plist --sign - ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME} COMMAND_ERROR_IS_FATAL ANY)") install(CODE "execute_process(COMMAND ${CODESIGN_PATH} --force --deep --sign - ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME} COMMAND_ERROR_IS_FATAL ANY)")
endif() endif()
endif() endif()
@@ -381,6 +306,9 @@ endfunction()
macro(configureCMake) macro(configureCMake)
message(STATUS "Configuring ImHex v${IMHEX_VERSION}") message(STATUS "Configuring ImHex v${IMHEX_VERSION}")
# Enable C and C++ languages
enable_language(C CXX)
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE) set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "Enable position independent code for all targets" FORCE)
# Configure use of recommended build tools # Configure use of recommended build tools
@@ -415,9 +343,9 @@ macro(configureCMake)
if (LD_LLD_PATH) if (LD_LLD_PATH)
set(CMAKE_LINKER ${LD_LLD_PATH}) set(CMAKE_LINKER ${LD_LLD_PATH})
if (NOT XCODE AND NOT MSVC) if (NOT XCODE)
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -fuse-ld=lld) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fuse-ld=lld) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
endif() endif()
else () else ()
message(WARNING "lld not found, using default linker!") message(WARNING "lld not found, using default linker!")
@@ -442,12 +370,18 @@ macro(configureCMake)
message(WARNING "LTO is not supported: ${output_error}") message(WARNING "LTO is not supported: ${output_error}")
endif () endif ()
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)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Disable deprecated warnings" FORCE)
endmacro() endmacro()
function(configureProject) function(configureProject)
# Enable C and C++ languages
enable_language(C CXX)
if (XCODE) if (XCODE)
# Support Xcode's multi configuration paradigm by placing built artifacts into separate directories # Support Xcode's multi configuration paradigm by placing built artifacts into separate directories
set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Configs/$<CONFIG>" PARENT_SCOPE) set(IMHEX_MAIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Configs/$<CONFIG>" PARENT_SCOPE)
@@ -463,14 +397,12 @@ macro(setDefaultBuiltTypeIfUnset)
endif() endif()
endmacro() endmacro()
function(loadVersion version plain_version) function(loadVersion version)
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION") set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${VERSION_FILE}) set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${VERSION_FILE})
file(READ "${VERSION_FILE}" read_version) file(READ "${VERSION_FILE}" read_version)
string(STRIP ${read_version} read_version) string(STRIP ${read_version} read_version)
string(REPLACE ".WIP" "" read_version_plain ${read_version})
set(${version} ${read_version} PARENT_SCOPE) set(${version} ${read_version} PARENT_SCOPE)
set(${plain_version} ${read_version_plain} PARENT_SCOPE)
endfunction() endfunction()
function(detectBadClone) function(detectBadClone)
@@ -497,8 +429,6 @@ function(verifyCompiler)
message(FATAL_ERROR "ImHex requires GCC 12.0.0 or newer. Please use the latest GCC version.") 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 "17.0.0") 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.") message(FATAL_ERROR "ImHex requires Clang 17.0.0 or newer. Please use the latest Clang version.")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
elseif (NOT (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) 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.") message(FATAL_ERROR "ImHex can only be compiled with GCC or Clang. ${CMAKE_CXX_COMPILER_ID} is not supported.")
endif() endif()
@@ -613,100 +543,67 @@ macro(setupDebugCompressionFlag)
if (NOT DEBUG_COMPRESSION_FLAG) # Cache variable if (NOT DEBUG_COMPRESSION_FLAG) # Cache variable
if (ZSTD_AVAILABLE_COMPILER AND ZSTD_AVAILABLE_LINKER) if (ZSTD_AVAILABLE_COMPILER AND ZSTD_AVAILABLE_LINKER)
message("Using Zstd compression for debug info because both compiler and linker support it")
set(DEBUG_COMPRESSION_FLAG "-gz=zstd" CACHE STRING "Cache to use for debug info compression") set(DEBUG_COMPRESSION_FLAG "-gz=zstd" CACHE STRING "Cache to use for debug info compression")
elseif (COMPRESS_AVAILABLE_COMPILER AND COMPRESS_AVAILABLE_LINKER) elseif (COMPRESS_AVAILABLE_COMPILER AND COMPRESS_AVAILABLE_LINKER)
message("Using default compression for debug info because both compiler and linker support it")
set(DEBUG_COMPRESSION_FLAG "-gz" CACHE STRING "Cache to use for debug info compression") set(DEBUG_COMPRESSION_FLAG "-gz" CACHE STRING "Cache to use for debug info compression")
else()
set(DEBUG_COMPRESSION_FLAG "" CACHE STRING "Cache to use for debug info compression")
endif() endif()
endif() endif()
addCommonFlag(${DEBUG_COMPRESSION_FLAG}) set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} ${DEBUG_COMPRESSION_FLAG}")
endmacro() endmacro()
macro(setupCompilerFlags target) macro(setupCompilerFlags target)
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") # IMHEX_COMMON_FLAGS: flags common for C, C++, Objective C, etc.. compilers
if (IMHEX_STRICT_WARNINGS)
addCommonFlag("/W4" ${target}) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
addCommonFlag("/wd4242" ${target})
addCommonFlag("/wd4244" ${target})
addCommonFlag("/wd4267" ${target})
addCommonFlag("/wd4996" ${target})
addCommonFlag("/wd4127" ${target})
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Define strict compilation flags # Define strict compilation flags
if (IMHEX_STRICT_WARNINGS) if (IMHEX_STRICT_WARNINGS)
addCommonFlag("-Wall" ${target}) set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wall -Wextra -Wpedantic -Werror")
addCommonFlag("-Wextra" ${target})
addCommonFlag("-Wpedantic" ${target})
addCommonFlag("-Werror" ${target})
endif() endif()
if (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") if (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
addCommonFlag("-rdynamic" ${target}) set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -rdynamic")
endif() endif()
addCXXFlag("-fexceptions" ${target}) set(IMHEX_CXX_FLAGS "-fexceptions -frtti")
addCXXFlag("-frtti" ${target})
# Disable some warnings # Disable some warnings
addCCXXFlag("-Wno-array-bounds" ${target}) set(IMHEX_C_CXX_FLAGS "-Wno-unknown-warning-option -Wno-array-bounds -Wno-deprecated-declarations -Wno-unknown-pragmas")
addCCXXFlag("-Wno-deprecated-declarations" ${target})
addCCXXFlag("-Wno-unknown-pragmas" ${target})
endif() endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (WIN32) if (IMHEX_ENABLE_UNITY_BUILD AND WIN32)
addLinkerFlag("-Wa,mbig-obj" ${target}) set(IMHEX_COMMON_FLAGS "${IMHEX_COMMON_FLAGS} -Wa,-mbig-obj")
endif () endif ()
endif() endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND APPLE)
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LLVM_PREFIX}/lib/c++")
addCCXXFlag("-Wno-unknown-warning-option" ${target})
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
addCommonFlag("/bigobj" ${target})
addCFlag("/std:clatest" ${target})
addCXXFlag("/std:c++latest" ${target})
endif()
# Disable some warnings for gcc # Disable some warnings for gcc
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
addCCXXFlag("-Wno-restrict" ${target}) set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -Wno-restrict -Wno-stringop-overread -Wno-stringop-overflow -Wno-dangling-reference")
addCCXXFlag("-Wno-stringop-overread" ${target})
addCCXXFlag("-Wno-stringop-overflow" ${target})
addCCXXFlag("-Wno-dangling-reference" ${target})
endif() endif()
# Define emscripten-specific disabled warnings # Define emscripten-specific disabled warnings
if (EMSCRIPTEN) if (EMSCRIPTEN)
addCCXXFlag("-pthread" ${target}) set(IMHEX_C_CXX_FLAGS "${IMHEX_C_CXX_FLAGS} -pthread -Wno-dollar-in-identifier-extension -Wno-pthreads-mem-growth")
addCCXXFlag("-Wno-dollar-in-identifier-extension" ${target})
addCCXXFlag("-Wno-pthreads-mem-growth" ${target})
endif () endif ()
if (IMHEX_COMPRESS_DEBUG_INFO) if (IMHEX_COMPRESS_DEBUG_INFO)
setupDebugCompressionFlag() setupDebugCompressionFlag()
endif() endif()
# Only generate minimal debug information for stacktraces in RelWithDebInfo builds # Set actual CMake flags
if (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS}")
addCCXXFlag("-g1" ${target}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${IMHEX_COMMON_FLAGS} ${IMHEX_C_CXX_FLAGS} ${IMHEX_CXX_FLAGS}")
endif() set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${IMHEX_COMMON_FLAGS}")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # Only generate minimal debug information for stacktraces in RelWithDebInfo builds
# Add flags for debug info in inline functions set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -g1")
addCCXXFlag("-gstatement-frontiers" ${target}) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g1")
addCCXXFlag("-ginline-points" ${target}) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif() # Add flags for debug info in inline functions
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -gstatement-frontiers -ginline-points")
endif() endif()
endmacro() endmacro()
@@ -738,7 +635,6 @@ macro(addBundledLibraries)
set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "") set(FPHSA_NAME_MISMATCHED ON CACHE BOOL "")
if(NOT USE_SYSTEM_FMT) if(NOT USE_SYSTEM_FMT)
set(FMT_INSTALL OFF CACHE BOOL "Disable install targets for libfmt" FORCE)
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL) add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/fmt EXCLUDE_FROM_ALL)
set(FMT_LIBRARIES fmt::fmt-header-only) set(FMT_LIBRARIES fmt::fmt-header-only)
else() else()
@@ -800,21 +696,16 @@ macro(addBundledLibraries)
set(JTHREAD_LIBRARIES jthread) set(JTHREAD_LIBRARIES jthread)
endif() endif()
if (USE_SYSTEM_BOOST)
find_package(Boost REQUIRED)
set(BOOST_LIBRARIES Boost::regex)
else()
add_subdirectory(${THIRD_PARTY_LIBS_FOLDER}/boost ${CMAKE_CURRENT_BINARY_DIR}/boost EXCLUDE_FROM_ALL)
set(BOOST_LIBRARIES boost::regex)
endif()
set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE) set(LIBPL_BUILD_CLI_AS_EXECUTABLE OFF CACHE BOOL "" FORCE)
set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE) set(LIBPL_ENABLE_PRECOMPILED_HEADERS ${IMHEX_ENABLE_PRECOMPILED_HEADERS} CACHE BOOL "" FORCE)
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE) if (WIN32)
set(LIBPL_SHARED_LIBRARY ON CACHE BOOL "" FORCE)
else()
set(LIBPL_SHARED_LIBRARY OFF CACHE BOOL "" FORCE)
endif()
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL) add_subdirectory(${EXTERNAL_LIBS_FOLDER}/pattern_language EXCLUDE_FROM_ALL)
add_subdirectory(${EXTERNAL_LIBS_FOLDER}/disassembler EXCLUDE_FROM_ALL)
if (LIBPL_SHARED_LIBRARY) if (LIBPL_SHARED_LIBRARY)
install( install(
@@ -839,30 +730,6 @@ macro(addBundledLibraries)
find_package(mbedTLS 3.4.0 REQUIRED) find_package(mbedTLS 3.4.0 REQUIRED)
find_package(Magic 5.39 REQUIRED) find_package(Magic 5.39 REQUIRED)
if (NOT IMHEX_DISABLE_STACKTRACE)
if (WIN32)
message(STATUS "StackWalk enabled!")
set(LIBBACKTRACE_LIBRARIES DbgHelp.lib)
else ()
find_package(Backtrace)
if (${Backtrace_FOUND})
message(STATUS "Backtrace enabled! Header: ${Backtrace_HEADER}")
if (Backtrace_HEADER STREQUAL "backtrace.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>)
add_compile_definitions(HEX_HAS_BACKTRACE)
elseif (Backtrace_HEADER STREQUAL "execinfo.h")
set(LIBBACKTRACE_LIBRARIES ${Backtrace_LIBRARY})
set(LIBBACKTRACE_INCLUDE_DIRS ${Backtrace_INCLUDE_DIR})
add_compile_definitions(BACKTRACE_HEADER=<${Backtrace_HEADER}>)
add_compile_definitions(HEX_HAS_EXECINFO)
endif()
endif()
endif()
endif()
endmacro() endmacro()
function(enableUnityBuild TARGET) function(enableUnityBuild TARGET)
@@ -871,20 +738,70 @@ function(enableUnityBuild TARGET)
endif () endif ()
endfunction() endfunction()
function(setSDKPaths) function(generatePDBs)
if (WIN32) if (NOT IMHEX_GENERATE_PDBS)
set(SDK_PATH "./sdk" PARENT_SCOPE) return()
elseif (APPLE) endif ()
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk" PARENT_SCOPE)
else() if (NOT WIN32 OR CMAKE_BUILD_TYPE STREQUAL "Debug")
set(SDK_PATH "share/imhex/sdk" PARENT_SCOPE) return()
endif() endif ()
include(FetchContent)
FetchContent_Declare(
cv2pdb
URL "https://github.com/rainers/cv2pdb/releases/download/v0.52/cv2pdb-0.52.zip"
DOWNLOAD_EXTRACT_TIMESTAMP ON
)
FetchContent_Populate(cv2pdb)
set(PDBS_TO_GENERATE main main-forwarder libimhex ${PLUGINS})
foreach (PDB ${PDBS_TO_GENERATE})
if (PDB STREQUAL "main")
set(GENERATED_PDB imhex)
elseif (PDB STREQUAL "main-forwarder")
set(GENERATED_PDB imhex-gui)
elseif (PDB STREQUAL "libimhex")
set(GENERATED_PDB libimhex)
else ()
set(GENERATED_PDB plugins/${PDB})
endif ()
if (IMHEX_REPLACE_DWARF_WITH_PDB)
set(PDB_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${GENERATED_PDB})
else ()
set(PDB_OUTPUT_PATH)
endif()
add_custom_target(${PDB}_pdb DEPENDS ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND
(
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb &&
${cv2pdb_SOURCE_DIR}/cv2pdb64.exe $<TARGET_FILE:${PDB}> ${PDB_OUTPUT_PATH} &&
${CMAKE_COMMAND} -E remove -f ${CMAKE_BINARY_DIR}/${GENERATED_PDB}
) || (exit 0)
COMMAND_EXPAND_LISTS)
install(FILES ${CMAKE_BINARY_DIR}/${GENERATED_PDB}.pdb DESTINATION ".")
add_dependencies(imhex_all ${PDB}_pdb)
endforeach ()
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk" PARENT_SCOPE)
endfunction() endfunction()
function(generateSDKDirectory) function(generateSDKDirectory)
setSDKPaths() if (WIN32)
set(SDK_PATH "./sdk")
elseif (APPLE)
set(SDK_PATH "${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}/Contents/Resources/sdk")
else()
set(SDK_PATH "share/imhex/sdk")
endif()
set(SDK_BUILD_PATH "${CMAKE_BINARY_DIR}/sdk")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE) install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/libimhex DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/external DESTINATION "${SDK_PATH}/lib") install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/external DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/imgui DESTINATION "${SDK_PATH}/lib/third_party" PATTERN "**/source/*" EXCLUDE) install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/imgui DESTINATION "${SDK_PATH}/lib/third_party" PATTERN "**/source/*" EXCLUDE)
@@ -894,20 +811,11 @@ function(generateSDKDirectory)
if (NOT USE_SYSTEM_NLOHMANN_JSON) if (NOT USE_SYSTEM_NLOHMANN_JSON)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party") install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/nlohmann_json DESTINATION "${SDK_PATH}/lib/third_party")
endif() endif()
if (NOT USE_SYSTEM_BOOST)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/third_party/boost DESTINATION "${SDK_PATH}/lib/third_party")
endif()
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/modules DESTINATION "${SDK_PATH}/cmake") install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/modules DESTINATION "${SDK_PATH}/cmake")
install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake") install(FILES ${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake DESTINATION "${SDK_PATH}/cmake")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}") install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/sdk/ DESTINATION "${SDK_PATH}")
install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib") install(TARGETS libimhex ARCHIVE DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/ui DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(TARGETS ui ARCHIVE DESTINATION "${SDK_PATH}/lib")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins/fonts DESTINATION "${SDK_PATH}/lib" PATTERN "**/source/*" EXCLUDE)
install(TARGETS fonts ARCHIVE DESTINATION "${SDK_PATH}/lib")
endfunction() endfunction()
function(addIncludesFromLibrary target library) function(addIncludesFromLibrary target library)

View File

@@ -89,5 +89,4 @@ if (CoreClrEmbed_INCLUDE_DIR AND CoreClrEmbed_LIBRARY)
set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}" CACHE STRING "CoreClrEmbed libraries" FORCE) set(CoreClrEmbed_LIBRARIES "${CoreClrEmbed_LIBRARY}" CACHE STRING "CoreClrEmbed libraries" FORCE)
set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}" CACHE STRING "CoreClrEmbed shared libraries" FORCE) set(CoreClrEmbed_SHARED_LIBRARIES "${CoreClrEmbed_SHARED_LIBRARY}" CACHE STRING "CoreClrEmbed shared libraries" FORCE)
set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}" CACHE STRING "CoreClrEmbed include directories" FORCE) set(CoreClrEmbed_INCLUDE_DIRS "${CoreClrEmbed_INCLUDE_DIR}" CACHE STRING "CoreClrEmbed include directories" FORCE)
set(CoreClrEmbed_VERSION "${CORECLR_RUNTIME_VERSION_FULL}" CACHE STRING "CoreClrEmbed version" FORCE)
endif() endif()

View File

@@ -1,60 +0,0 @@
find_path(LZ4_INCLUDE_DIR
NAMES lz4.h
HINTS "${LZ4_INCLUDEDIR}" "${LZ4_HINTS}/include"
PATHS
/usr/local/include
/usr/include
)
find_library(LZ4_LIBRARY
NAMES lz4 liblz4
HINTS "${LZ4_LIBDIR}" "${LZ4_HINTS}/lib"
PATHS
/usr/local/lib
/usr/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args( LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR )
if( LZ4_FOUND )
include( CheckIncludeFile )
include( CMakePushCheckState )
set( LZ4_INCLUDE_DIRS ${LZ4_INCLUDE_DIR} )
set( LZ4_LIBRARIES ${LZ4_LIBRARY} )
cmake_push_check_state()
set( CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIRS} )
check_include_file( lz4frame.h HAVE_LZ4FRAME_H )
cmake_pop_check_state()
if (WIN32)
set ( LZ4_DLL_DIR "${LZ4_HINTS}/bin"
CACHE PATH "Path to LZ4 DLL"
)
file( GLOB _lz4_dll RELATIVE "${LZ4_DLL_DIR}"
"${LZ4_DLL_DIR}/lz4*.dll"
)
set ( LZ4_DLL ${_lz4_dll}
# We're storing filenames only. Should we use STRING instead?
CACHE FILEPATH "LZ4 DLL file name"
)
file( GLOB _lz4_pdb RELATIVE "${LZ4_DLL_DIR}"
"${LZ4_DLL_DIR}/lz4*.pdb"
)
set ( LZ4_PDB ${_lz4_pdb}
CACHE FILEPATH "LZ4 PDB file name"
)
mark_as_advanced( LZ4_DLL_DIR LZ4_DLL LZ4_PDB )
endif()
else()
set( LZ4_INCLUDE_DIRS )
set( LZ4_LIBRARIES )
endif()
mark_as_advanced( LZ4_LIBRARIES LZ4_INCLUDE_DIRS )
add_library( LZ4::lz4 INTERFACE IMPORTED )
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LZ4_INCLUDE_DIRS} )
set_property( TARGET LZ4::lz4 PROPERTY INTERFACE_LINK_LIBRARIES ${LZ4_LIBRARIES} )

View File

@@ -39,7 +39,3 @@ if (ZSTD_FOUND)
endif() endif()
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY) mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
add_library(ZSTD::zstd INTERFACE IMPORTED)
set_property(TARGET ZSTD::zstd PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${ZSTD_INCLUDE_DIR})
set_property(TARGET ZSTD::zstd PROPERTY INTERFACE_LINK_LIBRARIES ${ZSTD_LIBRARY})

View File

@@ -40,12 +40,7 @@ IF(MBEDTLS_FOUND)
STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE})
STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE})
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
if (MSVC)
SET(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY_FILE}.lib ${MBEDX509_LIBRARY_FILE}.lib ${MBEDCRYPTO_LIBRARY_FILE}.lib)
else()
SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}")
endif()
IF(NOT MBEDTLS_FIND_QUIETLY) IF(NOT MBEDTLS_FIND_QUIETLY)
MESSAGE(STATUS "Found mbedTLS:") MESSAGE(STATUS "Found mbedTLS:")
@@ -60,9 +55,9 @@ IF(MBEDTLS_FOUND)
MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}")
ENDIF(NOT MBEDTLS_FIND_QUIETLY) ENDIF(NOT MBEDTLS_FIND_QUIETLY)
ELSE(MBEDTLS_FOUND) ELSE(MBEDTLS_FOUND)
IF(mbedTLS_FIND_REQUIRED) IF(MBEDTLS_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find mbedTLS") MESSAGE(FATAL_ERROR "Could not find mbedTLS")
ENDIF(mbedTLS_FIND_REQUIRED) ENDIF(MBEDTLS_FIND_REQUIRED)
ENDIF(MBEDTLS_FOUND) ENDIF(MBEDTLS_FOUND)
MARK_AS_ADVANCED( MARK_AS_ADVANCED(

View File

@@ -1,5 +1,4 @@
macro(add_imhex_plugin) macro(add_imhex_plugin)
setSDKPaths()
# Parse arguments # Parse arguments
set(options LIBRARY_PLUGIN) set(options LIBRARY_PLUGIN)
set(oneValueArgs NAME IMHEX_VERSION) set(oneValueArgs NAME IMHEX_VERSION)
@@ -29,10 +28,6 @@ macro(add_imhex_plugin)
endif() endif()
endif() endif()
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION "${SDK_PATH}/lib/plugins/${IMHEX_PLUGIN_NAME}")
endif()
# Define new project for plugin # Define new project for plugin
project(${IMHEX_PLUGIN_NAME}) project(${IMHEX_PLUGIN_NAME})
@@ -42,7 +37,7 @@ macro(add_imhex_plugin)
# Add include directories and link libraries # Add include directories and link libraries
target_include_directories(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_INCLUDES}) target_include_directories(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_INCLUDES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_LIBRARIES}) target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_LIBRARIES})
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} imgui_all_includes libwolv) target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE libimhex ${FMT_LIBRARIES} imgui_all_includes libwolv tracing)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl) addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl)
addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl-gen) addIncludesFromLibrary(${IMHEX_PLUGIN_NAME} libpl-gen)
@@ -67,11 +62,7 @@ macro(add_imhex_plugin)
) )
# Set rpath of plugin libraries to the plugins folder # Set rpath of plugin libraries to the plugins folder
if (WIN32) if (APPLE)
if (IMHEX_PLUGIN_LIBRARY_PLUGIN)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
endif()
elseif (APPLE)
set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES BUILD_RPATH "@executable_path/../Frameworks;@executable_path/plugins") set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES BUILD_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
endif() endif()
@@ -81,23 +72,10 @@ macro(add_imhex_plugin)
add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs) add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs)
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY}) target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
set(FEATURE_DEFINE_CONTENT) foreach(feature ${IMHEX_PLUGIN_FEATURES})
string(TOUPPER ${feature} feature)
if (IMHEX_PLUGIN_FEATURES) add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
list(LENGTH IMHEX_PLUGIN_FEATURES IMHEX_FEATURE_COUNT) endforeach()
math(EXPR IMHEX_FEATURE_COUNT "${IMHEX_FEATURE_COUNT} - 1" OUTPUT_FORMAT DECIMAL)
foreach(index RANGE 0 ${IMHEX_FEATURE_COUNT} 2)
list(SUBLIST IMHEX_PLUGIN_FEATURES ${index} 2 IMHEX_PLUGIN_FEATURE)
list(GET IMHEX_PLUGIN_FEATURE 0 feature_define)
list(GET IMHEX_PLUGIN_FEATURE 1 feature_description)
string(TOUPPER ${feature_define} feature_define)
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature_define}=0)
set(FEATURE_DEFINE_CONTENT "${FEATURE_DEFINE_CONTENT}{ \"${feature_description}\", IMHEX_FEATURE_ENABLED(${feature_define}) },")
endforeach()
endif()
target_compile_options(${IMHEX_PLUGIN_NAME} PRIVATE -DIMHEX_PLUGIN_FEATURES_CONTENT=${FEATURE_DEFINE_CONTENT})
# Add the new plugin to the main dependency list so it gets built by default # Add the new plugin to the main dependency list so it gets built by default
if (TARGET imhex_all) if (TARGET imhex_all)
@@ -110,28 +88,12 @@ macro(add_imhex_plugin)
# Fix rpath # Fix rpath
if (APPLE) if (APPLE)
set_target_properties( set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/plugins")
${IMHEX_PLUGIN_NAME}
PROPERTIES
INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/plugins"
)
elseif (UNIX) elseif (UNIX)
set(PLUGIN_RPATH "") set_target_properties(${IMHEX_PLUGIN_NAME} PROPERTIES INSTALL_RPATH_USE_ORIGIN ON INSTALL_RPATH "$ORIGIN/")
list(APPEND PLUGIN_RPATH "$ORIGIN")
if (IMHEX_PLUGIN_ADD_INSTALL_PREFIX_TO_RPATH)
list(APPEND PLUGIN_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
endif()
set_target_properties(
${IMHEX_PLUGIN_NAME}
PROPERTIES
INSTALL_RPATH_USE_ORIGIN ON
INSTALL_RPATH "${PLUGIN_RPATH}"
)
endif() endif()
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt AND IMHEX_ENABLE_UNIT_TESTS AND IMHEX_ENABLE_PLUGIN_TESTS) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt AND IMHEX_ENABLE_UNIT_TESTS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tests)
target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_NAME}_tests) target_link_libraries(${IMHEX_PLUGIN_NAME} PUBLIC ${IMHEX_PLUGIN_NAME}_tests)
target_compile_definitions(${IMHEX_PLUGIN_NAME}_tests PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}-tests") target_compile_definitions(${IMHEX_PLUGIN_NAME}_tests PRIVATE IMHEX_PROJECT_NAME="${IMHEX_PLUGIN_NAME}-tests")
@@ -139,10 +101,6 @@ macro(add_imhex_plugin)
endmacro() endmacro()
macro(add_romfs_resource input output) macro(add_romfs_resource input output)
if (NOT EXISTS ${input})
message(WARNING "Resource file ${input} does not exist")
endif()
configure_file(${input} ${CMAKE_CURRENT_BINARY_DIR}/romfs/${output} COPYONLY) configure_file(${input} ${CMAKE_CURRENT_BINARY_DIR}/romfs/${output} COPYONLY)
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs) list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)

View File

@@ -29,21 +29,22 @@ add_subdirectory_if_exists(lib/third_party/nlohmann_json)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json PARENT_SCOPE) set(NLOHMANN_JSON_LIBRARIES nlohmann_json PARENT_SCOPE)
set(NLOHMANN_JSON_LIBRARIES nlohmann_json) set(NLOHMANN_JSON_LIBRARIES nlohmann_json)
add_subdirectory_if_exists(lib/third_party/boost)
set(BOOST_LIBRARIES boost::regex PARENT_SCOPE)
set(BOOST_LIBRARIES boost::regex)
add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL) add_subdirectory(lib/external/libwolv EXCLUDE_FROM_ALL)
set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE) set(LIBPL_ENABLE_CLI OFF CACHE BOOL "" FORCE)
add_subdirectory(lib/external/pattern_language EXCLUDE_FROM_ALL) add_subdirectory(lib/external/pattern_language EXCLUDE_FROM_ALL)
find_package(CURL REQUIRED)
find_package(mbedTLS 3.4.0 REQUIRED)
set(CURL_LIBRARIES ${CURL_LIBRARIES} PARENT_SCOPE)
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARIES} PARENT_SCOPE)
add_subdirectory(lib/libimhex) add_subdirectory(lib/libimhex)
if (WIN32) if (WIN32)
set_target_properties(libimhex PROPERTIES set_target_properties(libimhex PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.dll" IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../libimhex.dll"
IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/liblibimhex.dll.a" IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex.dll.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include") INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/lib/libimhex/include")
elseif (APPLE) elseif (APPLE)
file(GLOB LIBIMHEX_DYLIB "${CMAKE_CURRENT_SOURCE_DIR}/../../Frameworks/libimhex.*.dylib") file(GLOB LIBIMHEX_DYLIB "${CMAKE_CURRENT_SOURCE_DIR}/../../Frameworks/libimhex.*.dylib")

View File

@@ -11,23 +11,31 @@ AppDir:
exec_args: $@ exec_args: $@
apt: apt:
arch: arch:
- "{{ARCHITECTURE_PACKAGE}}" - amd64
allow_unauthenticated: true allow_unauthenticated: true
sources: sources:
- sourceline: 'deb [arch=amd64] http://us.archive.ubuntu.com/ubuntu/ oracular main restricted universe multiverse' - sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy main restricted
- sourceline: 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ oracular main restricted universe multiverse' - sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy universe
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates universe
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy multiverse
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
- sourceline: deb http://us.archive.ubuntu.com/ubuntu/ jammy-backports main restricted
universe multiverse
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security main restricted
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse
include: include:
- librsvg2-common - librsvg2-common
- libbz2-1.0 - libbz2-1.0:amd64
- libcap2 - libcap2:amd64
- libdbus-1-3 - libdbus-1-3:amd64
- libfontconfig1 - libgpg-error0:amd64
- libgpg-error0 - liblzma5:amd64
- liblzma5 - libnss-mdns:amd64
- libnss-mdns - libpcre3:amd64
- libpcre3 - libselinux1:amd64
- libselinux1 - libtinfo6:amd64
- libtinfo6
files: files:
include: include:
- /lib/x86_64-linux-gnu/libLLVM-13.so.1 - /lib/x86_64-linux-gnu/libLLVM-13.so.1
@@ -124,6 +132,6 @@ AppDir:
- usr/share/doc/*/NEWS.* - usr/share/doc/*/NEWS.*
- usr/share/doc/*/TODO.* - usr/share/doc/*/TODO.*
AppImage: AppImage:
arch: "{{ARCHITECTURE_APPIMAGE_BUILDER}}" arch: x86_64
update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-{{ARCHITECTURE_FILE_NAME}}.AppImage.zsync update-information: gh-releases-zsync|WerWolv|ImHex|latest|imhex-*-x86_64.AppImage.zsync
file_name: imhex-{{VERSION}}-{{ARCHITECTURE_FILE_NAME}}.AppImage file_name: imhex-{{VERSION}}-x86_64.AppImage

View File

@@ -13,7 +13,6 @@ RUN pacman -S --needed --noconfirm \
glfw-x11 \ glfw-x11 \
file \ file \
mbedtls \ mbedtls \
fontconfig \
freetype2 \ freetype2 \
curl \ curl \
dbus \ dbus \

4
dist/Arch/PKGBUILD vendored
View File

@@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
arch=("x86_64") arch=("x86_64")
url="https://github.com/WerWolv/ImHex" url="https://github.com/WerWolv/ImHex"
license=('GPL2') license=('GPL2')
depends=(glfw mbedtls fontconfig freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd) depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd)
makedepends=(git) makedepends=(git)
provides=(imhex) provides=(imhex)
conflicts=(imhex) conflicts=(imhex)
@@ -26,5 +26,5 @@ package() {
install -d "$pkgdir/usr/share/imhex" install -d "$pkgdir/usr/share/imhex"
cp -r "$srcdir/usr/share/imhex/"{constants,encodings,includes,magic,patterns} "$pkgdir/usr/share/imhex" cp -r "$srcdir/usr/share/imhex/"{constants,encodings,includes,magic,patterns} "$pkgdir/usr/share/imhex"
cp -r "$srcdir/usr/share/"{applications,licenses,pixmaps,mime} "$pkgdir/usr/share" cp -r "$srcdir/usr/share/"{applications,licenses,pixmaps} "$pkgdir/usr/share"
} }

View File

@@ -6,6 +6,7 @@ brew "freetype2"
brew "libmagic" brew "libmagic"
brew "pkg-config" brew "pkg-config"
brew "curl" brew "curl"
brew "gcc@12"
brew "llvm" brew "llvm"
brew "glfw" brew "glfw"
brew "ninja" brew "ninja"

View File

@@ -4,7 +4,7 @@ Section: editors
Priority: optional Priority: optional
Architecture: amd64 Architecture: amd64
License: GNU GPL-2 License: GNU GPL-2
Depends: libfontconfig1, libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
Maintainer: WerWolv <hey@werwolv.net> Maintainer: WerWolv <hey@werwolv.net>
Description: ImHex Hex Editor Description: ImHex Hex Editor
A Hex Editor for Reverse Engineers, Programmers and A Hex Editor for Reverse Engineers, Programmers and

View File

@@ -20,14 +20,13 @@ DEPEND=""
RDEPEND="${DEPEND} RDEPEND="${DEPEND}
media-libs/glfw media-libs/glfw
sys-apps/file sys-apps/file
net-libs/mbedtls dev-libs/mbedtls
dev-cpp/nlohmann_json dev-cpp/nlohmann_json
sys-apps/dbus dbus
sys-apps/xdg-desktop-portal xdg-desktop-portal
sys-libs/zlib sys-libs/zlib
app-arch/bzip2 app-arch/bzip2
app-arch/lzma app-arch/lzma
app-arch/zstd app-arch/zstd
app-arch/lz4
" "
BDEPEND="${DEPEND}" BDEPEND="${DEPEND}"

View File

@@ -1,4 +1,4 @@
FROM ubuntu:24.10 as build FROM ubuntu:22.04 as build
# Used to invalidate layer cache but not mount cache # Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493 # See https://github.com/moby/moby/issues/41715#issuecomment-733976493
@@ -14,13 +14,24 @@ apt update
# general deps # general deps
apt install -y ccache git wget apt install -y ccache git wget
# appimage tools deps # appimage tools deps
apt install -y python3-pip python3-venv python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse ninja-build
apt install -y squashfs-tools zsync apt install -y squashfs-tools zsync
# imhex deps # imhex deps
/tmp/get_deps_debian.sh /tmp/get_deps_debian.sh
EOF EOF
RUN --mount=type=cache,target=/cache <<EOF
# Download appimage-builder
set -xe
mkdir -p /cache/bin
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /cache/bin/appimagetool || true
chmod +x /cache/bin/appimagetool
pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
EOF
ENV PATH="/cache/bin/:${PATH}" ENV PATH="/cache/bin/:${PATH}"
# Copy Imhex source # Copy Imhex source
@@ -30,19 +41,13 @@ ARG LTO=ON
ARG BUILD_TYPE=RelWithDebInfo ARG BUILD_TYPE=RelWithDebInfo
ARG GIT_COMMIT_HASH ARG GIT_COMMIT_HASH
ARG GIT_BRANCH ARG GIT_BRANCH
ARG ARCHITECTURE_PACKAGE
ARG ARCHITECTURE_FILE_NAME
ARG ARCHITECTURE_APPIMAGE_BUILDER
WORKDIR /build WORKDIR /build
SHELL ["bash", "-c"] # Ubuntu sh doesnt support string substitution
# Ubuntu sh doesnt support string substitution
SHELL ["bash", "-c"]
RUN <<EOF RUN <<EOF
# Prepare ImHex build # Prepare ImHex build
set -xe set -xe
CC=gcc-14 CXX=g++-14 cmake -G "Ninja" \ CC=gcc-12 CXX=g++-12 cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="/usr" \ -DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -66,23 +71,11 @@ ccache -s
EOF EOF
RUN <<EOF RUN <<EOF
# Download appimage-builder # Package ImHex as AppImage
set -xe set -xe
mkdir -p /cache/bin
wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /cache/bin/appimagetool || true
chmod +x /cache/bin/appimagetool
python3 -m venv venv
. venv/bin/activate
pip3 install git+https://github.com/AppImageCrafters/appimage-builder@f38699e
# Package ImHex as AppImage
export VERSION=$(cat /imhex/VERSION) export VERSION=$(cat /imhex/VERSION)
export ARCHITECTURE_PACKAGE=${ARCHITECTURE_PACKAGE} appimage-builder --recipe /imhex/dist/AppImageBuilder.yml
export ARCHITECTURE_FILE_NAME=${ARCHITECTURE_FILE_NAME}
export ARCHITECTURE_APPIMAGE_BUILDER=${ARCHITECTURE_APPIMAGE_BUILDER}
appimage-builder --recipe /imhex/dist/AppImage/AppImageBuilder.yml
EOF EOF
FROM scratch FROM scratch

View File

@@ -3,7 +3,7 @@
On macOS, ImHex is built through regular GCC and LLVM clang. On macOS, ImHex is built through regular GCC and LLVM clang.
1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules` 1. Clone the repo using `git clone https://github.com/WerWolv/ImHex --recurse-submodules`
2. Install all the dependencies using `brew bundle --no-lock --file dist/macOS/Brewfile` 2. Install all the dependencies using `brew bundle --no-lock --file dist/Brewfile`
3. Build ImHex itself using the following commands: 3. Build ImHex itself using the following commands:
```sh ```sh
cd ImHex cd ImHex

View File

@@ -1,48 +0,0 @@
import subprocess
import sys
def get_commits(branch: str, start_tag: str, end_tag: str) -> list[str]:
try:
commits_raw = subprocess.check_output([ "git", "--no-pager", "log", branch, "--no-color", "--pretty=oneline", "--abbrev-commit", f"{start_tag}..{end_tag}"], stderr=subprocess.DEVNULL).decode("UTF-8").split("\n")
except:
return []
commits = []
for line in commits_raw:
commits.append(line[9:])
return commits
def main(args: list) -> int:
if len(args) != 2:
print(f"Usage: {args[0]} prev_minor")
return 1
last_minor_version = f"v1.{args[1]}"
master_commits = get_commits("master", f"{last_minor_version}.0", "master")
for i in range(1, 100):
branch_commits = get_commits(f"releases/{last_minor_version}.X", f"{last_minor_version}.0", f"{last_minor_version}.{i}")
if len(branch_commits) == 0:
break
master_commits = [commit for commit in master_commits if commit not in branch_commits]
sorted_commits = {}
for commit in master_commits:
category, commit_name = commit.split(":", 1)
if category not in sorted_commits:
sorted_commits[category] = []
sorted_commits[category].append(commit_name)
for category in sorted_commits:
print(f"## {category}\n")
for commit in sorted_commits[category]:
print(f"- {commit}")
print(f"\n")
if __name__ == "__main__":
exit(main(sys.argv))

View File

@@ -5,7 +5,6 @@ pacman -S $@ --needed \
gcc \ gcc \
lld \ lld \
glfw \ glfw \
fontconfig \
file \ file \
mbedtls \ mbedtls \
freetype2 \ freetype2 \
@@ -19,5 +18,4 @@ pacman -S $@ --needed \
zlib \ zlib \
bzip2 \ bzip2 \
xz \ xz \
zstd \ zstd
lz4

View File

@@ -8,8 +8,8 @@ fi
apt install -y \ apt install -y \
build-essential \ build-essential \
gcc-14 \ gcc-12 \
g++-14 \ g++-12 \
lld \ lld \
${PKGCONF:-} \ ${PKGCONF:-} \
cmake \ cmake \
@@ -18,7 +18,6 @@ apt install -y \
libglm-dev \ libglm-dev \
libmagic-dev \ libmagic-dev \
libmbedtls-dev \ libmbedtls-dev \
libfontconfig-dev \
libfreetype-dev \ libfreetype-dev \
libdbus-1-dev \ libdbus-1-dev \
libcurl4-gnutls-dev \ libcurl4-gnutls-dev \
@@ -27,5 +26,4 @@ apt install -y \
zlib1g-dev \ zlib1g-dev \
libbz2-dev \ libbz2-dev \
liblzma-dev \ liblzma-dev \
libzstd-dev \ libzstd-dev
liblz4-dev

View File

@@ -4,7 +4,6 @@ dnf install -y \
cmake \ cmake \
dbus-devel \ dbus-devel \
file-devel \ file-devel \
fontconfig-devel \
freetype-devel \ freetype-devel \
libcurl-devel \ libcurl-devel \
gcc-c++ \ gcc-c++ \
@@ -17,5 +16,4 @@ dnf install -y \
libzstd-devel \ libzstd-devel \
zlib-devel \ zlib-devel \
bzip2-devel \ bzip2-devel \
xz-devel \ xz-devel
lz4-devel

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
pacman -S --needed --noconfirm pactoys unzip pacman -S --needed --noconfirm pactoys
pacboy -S --needed --noconfirm \ pacboy -S --needed --noconfirm \
gcc:p \ gcc:p \
lld:p \ lld:p \
@@ -17,5 +17,4 @@ pacboy -S --needed --noconfirm \
zlib:p \ zlib:p \
bzip2:p \ bzip2:p \
xz:p \ xz:p \
zstd:p \ zstd:p
lz4:p

View File

@@ -3,9 +3,8 @@
zypper install \ zypper install \
cmake \ cmake \
ninja \ ninja \
gcc14 \ gcc12 \
gcc14-c++ \ gcc12-c++ \
fontconfig-devel \
freetype2-devel \ freetype2-devel \
libcurl-devel \ libcurl-devel \
dbus-1-devel \ dbus-1-devel \
@@ -17,5 +16,4 @@ zypper install \
libzstd-devel \ libzstd-devel \
zlib-devel \ zlib-devel \
bzip3-devel \ bzip3-devel \
xz-devel \ xz-devel
lz4-dev

8
dist/imhex.desktop vendored
View File

@@ -1,5 +1,4 @@
[Desktop Entry] [Desktop Entry]
Version=1.0
Name=ImHex Name=ImHex
Comment=ImHex Hex Editor Comment=ImHex Hex Editor
GenericName=Hex Editor GenericName=Hex Editor
@@ -9,10 +8,3 @@ Type=Application
StartupNotify=true StartupNotify=true
Categories=Development;IDE; Categories=Development;IDE;
StartupWMClass=imhex StartupWMClass=imhex
Keywords=static-analysis;reverse-engineering;disassembler;disassembly;hacking;forensics;hex-editor;cybersecurity;security;binary-analysis;
MimeType=application/vnd.imhex.proj;
Actions=NewFile;
[Desktop Action NewFile]
Exec=imhex --new
Name=Create New File

8
dist/imhex.mime.xml vendored
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/vnd.imhex.proj">
<comment>ImHex Project</comment>
<glob pattern="*.hexproj"/>
</mime-type>
</mime-info>

16
dist/langtool.py vendored
View File

@@ -129,19 +129,16 @@ def main():
key in lang_data["translations"] key in lang_data["translations"]
and lang_data["translations"][key] != INVALID_TRANSLATION and lang_data["translations"][key] != INVALID_TRANSLATION
) )
if ( if not has_translation and not (
has_translation (command == "retranslate" or command == "untranslate")
and not ( and re.compile(args.keys).fullmatch(key)
(command == "retranslate" or command == "untranslate")
and re.compile(args.keys).fullmatch(key)
)
and not command == "fmtzh"
): ):
continue continue
if command == "check": if command == "check":
print( print(
f"Error: Translation {lang_data['code']} is missing translation for key '{key}'" f"Error: Translation {lang_data['code']} is missing translation for key '{key}'"
) )
exit(2)
elif ( elif (
command == "translate" command == "translate"
or command == "retranslate" or command == "retranslate"
@@ -151,10 +148,7 @@ def main():
continue continue
reference_tranlsation = ( reference_tranlsation = (
" '%s'" % reference_lang_data["translations"][key] " '%s'" % reference_lang_data["translations"][key]
if ( if reference_lang_data
reference_lang_data
and key in reference_lang_data["translations"]
)
else "" else ""
) )
print( print(

View File

@@ -1,21 +1,10 @@
# This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile # This base image is also known as "crosscompile". See arm64.crosscompile.Dockerfile
FROM ghcr.io/itrooz/macos-crosscompile:clang19-nosdk as build FROM ghcr.io/itrooz/macos-crosscompile:clang17-nosdk as build
ENV MACOSX_DEPLOYMENT_TARGET 13.0 ENV MACOSX_DEPLOYMENT_TARGET 12.1
# -- DOWNLOADING STUFF # -- DOWNLOADING STUFF
# Update vcpkg
RUN <<EOF
cp /vcpkg/triplets/community/arm-osx-mytriplet.cmake /tmp/arm-osx-mytriplet.cmake
git -C /vcpkg clean -ffdx
git -C /vcpkg checkout origin/master
git -C /vcpkg reset --hard
git -C /vcpkg pull
/vcpkg/bootstrap-vcpkg.sh
cp /tmp/arm-osx-mytriplet.cmake /vcpkg/triplets/community/arm-osx-mytriplet.cmake
EOF
## Install make ## Install make
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y make
@@ -46,7 +35,7 @@ EOF
## Download libmagic ## Download libmagic
### Clone libmagic ### Clone libmagic
RUN git clone --depth 1 --branch FILE5_46 https://github.com/file/file /mnt/file RUN git clone --depth 1 --branch FILE5_45 https://github.com/file/file /mnt/file
### Download libmagic dependencies ### Download libmagic dependencies
RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y libtool autoconf RUN --mount=type=cache,target=/var/lib/apt/lists/ apt update && apt install -y libtool autoconf
@@ -129,7 +118,7 @@ if [ "$CUSTOM_GLFW" ]; then
cd /mnt/glfw cd /mnt/glfw
mkdir build mkdir build
cd build cd build
CC=o64-clang CXX=o64-clang++ cmake -G "Ninja" \ CC=o64-gcc CXX=o64-g++ cmake -G "Ninja" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DBUILD_SHARED_LIBS=ON \ -DBUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
@@ -137,7 +126,7 @@ if [ "$CUSTOM_GLFW" ]; then
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \ -DCMAKE_INSTALL_PREFIX=/vcpkg/installed/arm-osx-mytriplet \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \ -DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 \
.. ..
ninja -j $JOBS install ninja -j $JOBS install
@@ -159,7 +148,7 @@ RUN --mount=type=cache,target=/cache --mount=type=cache,target=/mnt/ImHex/build/
`# ccache flags` \ `# ccache flags` \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_OBJC_COMPILER_LAUNCHER=ccache -DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
`# MacOS cross-compiling flags` \ `# MacOS cross-compiling flags` \
-DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 \ -DVCPKG_TARGET_TRIPLET=arm-osx-mytriplet -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/osxcross/target/toolchain.cmake -DCMAKE_OSX_SYSROOT=/osxcross/target/SDK/MacOSX14.0.sdk -DCMAKE_OSX_DEPLOYMENT_TARGET=12.1 \
`# Override compilers for code generators` \ `# Override compilers for code generators` \
-DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \ -DNATIVE_CMAKE_C_COMPILER=/usr/bin/clang -DNATIVE_CMAKE_CXX_COMPILER=/usr/bin/clang++ \
`# Normal ImHex flags` \ `# Normal ImHex flags` \

View File

@@ -1,4 +1,4 @@
# This image is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile # This image is is provided for reference, but a (probably more up to date) image should be available at https://github.com/iTrooz/macos-crosscompile
FROM ubuntu:22.04 FROM ubuntu:22.04
ENV PATH $PATH:/osxcross/target/bin ENV PATH $PATH:/osxcross/target/bin
@@ -68,6 +68,19 @@ RUN --mount=type=cache,target=/cache <<EOF
ccache -s ccache -s
EOF EOF
# Not needed, because we don't use gcc for cross-compiling anymore
# ## Install dependencies for gcc-13
# RUN apt install -y gcc g++ zlib1g-dev libmpc-dev libmpfr-dev libgmp-dev
# ## Build cross-compiler gcc-13
# RUN --mount=type=cache,target=/cache <<EOF
# set -xe
# ccache -zs
# cd /osxcross
# UNATTENDED=1 CC=/usr/lib/ccache/gcc CXX=/usr/lib/ccache/g++ GCC_VERSION=13.2.0 ./build_gcc.sh
# ccache -s
# EOF
ARG DELETE_SDK=1 ARG DELETE_SDK=1
RUN <<EOF RUN <<EOF

21
dist/rpm/imhex.spec vendored
View File

@@ -1,5 +1,3 @@
%define source_date_epoch_from_changelog 0
Name: imhex Name: imhex
Version: VERSION Version: VERSION
Release: 0%{?dist} Release: 0%{?dist}
@@ -16,7 +14,6 @@ BuildRequires: cmake
BuildRequires: desktop-file-utils BuildRequires: desktop-file-utils
BuildRequires: dbus-devel BuildRequires: dbus-devel
BuildRequires: file-devel BuildRequires: file-devel
BuildRequires: fontconfig-devel
BuildRequires: freetype-devel BuildRequires: freetype-devel
BuildRequires: fmt-devel BuildRequires: fmt-devel
BuildRequires: gcc-c++ BuildRequires: gcc-c++
@@ -35,7 +32,7 @@ BuildRequires: zlib-devel
BuildRequires: bzip2-devel BuildRequires: bzip2-devel
BuildRequires: xz-devel BuildRequires: xz-devel
%if 0%{?rhel} %if 0%{?rhel}
BuildRequires: gcc-toolset-14 BuildRequires: gcc-toolset-12
%endif %endif
Provides: bundled(gnulib) Provides: bundled(gnulib)
@@ -71,9 +68,9 @@ rm -rf lib/third_party/{fmt,nlohmann_json,yara}
%build %build
%if 0%{?rhel} %if 0%{?rhel}
. /opt/rh/gcc-toolset-14/enable . /opt/rh/gcc-toolset-12/enable
%set_build_flags %set_build_flags
CXXFLAGS+=" -std=gnu++23" CXXFLAGS+=" -std=gnu++2b"
%endif %endif
%cmake \ %cmake \
-D CMAKE_BUILD_TYPE=Release \ -D CMAKE_BUILD_TYPE=Release \
@@ -94,9 +91,9 @@ CXXFLAGS+=" -std=gnu++23"
%check %check
%if 0%{?rhel} %if 0%{?rhel}
. /opt/rh/gcc-toolset-14/enable . /opt/rh/gcc-toolset-12/enable
%set_build_flags %set_build_flags
CXXFLAGS+=" -std=gnu++23" CXXFLAGS+=" -std=gnu++2b"
%endif %endif
@@ -123,11 +120,11 @@ cp -a lib/third_party/xdgpp/LICENSE %{buildroot
%doc README.md %doc README.md
%{_bindir}/imhex %{_bindir}/imhex
%{_bindir}/imhex-updater %{_bindir}/imhex-updater
%{_datadir}/pixmaps/%{name}.svg %{_datadir}/pixmaps/%{name}.png
%{_datadir}/applications/%{name}.desktop %{_datadir}/applications/%{name}.desktop
%{_datadir}/mime/packages/%{name}.xml
%{_libdir}/libimhex.so* %{_libdir}/libimhex.so*
%{_libdir}/%{name}/ %{_libdir}/%{name}/
%{_libdir}/*.hexpluglib
/usr/lib/debug/%{_libdir}/*.debug
%{_metainfodir}/net.werwolv.%{name}.metainfo.xml %{_metainfodir}/net.werwolv.%{name}.metainfo.xml
%changelog

16
dist/vcpkg.json vendored
View File

@@ -1,16 +0,0 @@
{
"name": "vcpkg",
"version": "1.0.0",
"builtin-baseline": "7e21420f775f72ae938bdeb5e6068f722088f06a",
"dependencies": [
"libmagic",
"freetype",
"mbedtls",
"zlib",
"bzip2",
"liblzma",
"zstd",
"glfw3",
"curl"
]
}

17
dist/web/Dockerfile vendored
View File

@@ -1,11 +1,11 @@
FROM emscripten/emsdk:3.1.51 AS build FROM emscripten/emsdk:3.1.51 as build
# Used to invalidate layer cache but not mount cache # Used to invalidate layer cache but not mount cache
# See https://github.com/moby/moby/issues/41715#issuecomment-733976493 # See https://github.com/moby/moby/issues/41715#issuecomment-733976493
ARG UNIQUEKEY 1 ARG UNIQUEKEY 1
RUN apt update RUN apt update
RUN apt install -y git ccache autoconf automake libtool cmake pkg-config ninja-build RUN apt install -y git ccache autoconf automake libtool cmake pkg-config
RUN <<EOF RUN <<EOF
# Install vcpkg # Install vcpkg
@@ -13,7 +13,6 @@ RUN <<EOF
set -xe set -xe
git clone https://github.com/microsoft/vcpkg /vcpkg git clone https://github.com/microsoft/vcpkg /vcpkg
git -C /vcpkg pull
/vcpkg/bootstrap-vcpkg.sh /vcpkg/bootstrap-vcpkg.sh
sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake sed -i 's/vcpkg_install_make(${EXTRA_ARGS})/vcpkg_install_make(${EXTRA_ARGS} SUBPATH src)/g' /vcpkg/ports/libmagic/portfile.cmake
EOF EOF
@@ -28,7 +27,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
' >> /emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake ' >> /emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
EOF EOF
ENV VCPKG_DEFAULT_BINARY_CACHE=/cache/vcpkg ENV VCPKG_DEFAULT_BINARY_CACHE /cache/vcpkg
RUN --mount=type=cache,target=/cache <<EOF RUN --mount=type=cache,target=/cache <<EOF
# Install dependencies with vcpkg # Install dependencies with vcpkg
set -xe set -xe
@@ -46,7 +45,7 @@ EOF
# Build ImHex # Build ImHex
ARG JOBS=4 ARG JOBS=4
ENV CCACHE_DIR=/cache/ccache ENV CCACHE_DIR /cache/ccache
RUN mkdir /build RUN mkdir /build
WORKDIR /build WORKDIR /build
@@ -57,7 +56,6 @@ set -xe
ccache -zs ccache -zs
cmake /imhex \ cmake /imhex \
-G "Ninja" \
-DIMHEX_OFFLINE_BUILD=ON \ -DIMHEX_OFFLINE_BUILD=ON \
-DIMHEX_STATIC_LINK_PLUGINS=ON \ -DIMHEX_STATIC_LINK_PLUGINS=ON \
-DIMHEX_EXCLUDE_PLUGINS="script_loader" \ -DIMHEX_EXCLUDE_PLUGINS="script_loader" \
@@ -68,10 +66,9 @@ cmake /imhex
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DCMAKE_TOOLCHAIN_FILE=/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \ -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DLIBROMFS_COMPRESS_RESOURCES=OFF \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=Release
ninja -j $JOBS make -j $JOBS
cp /imhex/dist/web/source/* /build cp /imhex/dist/web/source/* /build
ccache -s ccache -s
@@ -81,7 +78,7 @@ EOF
# See https://stackoverflow.com/questions/41701849/cannot-modify-accept-encoding-with-fetch https://github.com/AnthumChris/fetch-progress-indicators/issues/13 # See https://stackoverflow.com/questions/41701849/cannot-modify-accept-encoding-with-fetch https://github.com/AnthumChris/fetch-progress-indicators/issues/13
RUN du -b /build/imhex.wasm | cut -f1 > imhex.wasm.size RUN du -b /build/imhex.wasm | cut -f1 > imhex.wasm.size
FROM scratch AS raw FROM scratch as raw
COPY --from=build [ \ COPY --from=build [ \
# ImHex \ # ImHex \
"/build/imhex.wasm", \ "/build/imhex.wasm", \
@@ -95,7 +92,7 @@ COPY --from=build [ \
"/build/wasm-config.js", \ "/build/wasm-config.js", \
"/build/enable-threads.js", \ "/build/enable-threads.js", \
"/build/favicon.ico", \ "/build/favicon.ico", \
"/build/icon.svg", \ "/build/icon.png", \
"/build/manifest.json", \ "/build/manifest.json", \
"/build/robots.txt", \ "/build/robots.txt", \
"/build/sitemap.xml", \ "/build/sitemap.xml", \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 122 KiB

BIN
dist/web/source/icon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

View File

@@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" version="1">
<rect style="opacity:0.2" width="55" height="10" x="5" y="-60" rx="1.41" transform="rotate(90)"/>
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-60" rx="1.41" transform="rotate(90)"/>
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-14" rx="1.41" transform="rotate(90)"/>
<rect style="fill:#2b50a1" width="55" height="10" x="4" y="-33" rx="1.41" transform="rotate(90)"/>
<path style="opacity:0.2" d="M 5.3808594,5 C 4.6158118,5 4,5.6158118 4,6.3808594 V 13.619141 C 4,14.384188 4.6158118,15 5.3808594,15 H 31.619141 C 32.384188,15 33,14.384188 33,13.619141 V 6.3808594 C 33,5.6158118 32.384188,5 31.619141,5 Z M 40.400391,5 C 39.624791,5 39,5.6247906 39,6.4003906 V 13.599609 C 39,14.375209 39.624791,15 40.400391,15 H 58.599609 C 59.375209,15 60,14.375209 60,13.599609 V 6.4003906 C 60,5.6247906 59.375209,5 58.599609,5 Z M 5.3808594,50 C 4.6158118,50 4,50.615812 4,51.380859 v 7.238282 C 4,59.384188 4.6158118,60 5.3808594,60 H 31.619141 C 32.384188,60 33,59.384188 33,58.619141 V 51.380859 C 33,50.615812 32.384188,50 31.619141,50 Z"/>
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="4" rx="1.381"/>
<rect style="fill:#3a6be0" width="21" height="10" x="39" y="4" rx="1.4"/>
<rect style="fill:#3a6be0" width="29" height="10" x="4" y="49" rx="1.381"/>
<path style="fill:#ffffff;opacity:0.1" d="M 5.3808594 4 C 4.6158118 4 4 4.6158118 4 5.3808594 L 4 6.3808594 C 4 5.6158118 4.6158118 5 5.3808594 5 L 31.619141 5 C 32.384188 5 33 5.6158118 33 6.3808594 L 33 5.3808594 C 33 4.6158118 32.384188 4 31.619141 4 L 5.3808594 4 z M 40.400391 4 C 39.624791 4 39 4.6247906 39 5.4003906 L 39 6.4003906 C 39 5.6247906 39.624791 5 40.400391 5 L 58.599609 5 C 59.375209 5 60 5.6247906 60 6.4003906 L 60 5.4003906 C 60 4.6247906 59.375209 4 58.599609 4 L 40.400391 4 z M 5.3808594 49 C 4.6158118 49 4 49.615812 4 50.380859 L 4 51.380859 C 4 50.615812 4.6158118 50 5.3808594 50 L 31.619141 50 C 32.384188 50 33 50.615812 33 51.380859 L 33 50.380859 C 33 49.615812 32.384188 49 31.619141 49 L 5.3808594 49 z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -11,7 +11,7 @@
<meta name="title" content="ImHex"> <meta name="title" content="ImHex">
<meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts."> <meta name="description" content="Free and extremely powerful Online Hex Editor for your Web Browser. ImHex is a free and open source Hex Editor for Reverse Engineers and Developers and Data Analysts.">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="apple-touch-icon" href="icon.svg"> <link rel="apple-touch-icon" href="icon.png">
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website"> <meta property="og:type" content="website">
@@ -38,7 +38,7 @@
"founder": "WerWolv", "founder": "WerWolv",
"slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.", "slogan": "A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.",
"url": "https://imhex.werwolv.net", "url": "https://imhex.werwolv.net",
"logo": "https://imhex.werwolv.net/assets/logos/logo.svg" "logo": "https://imhex.werwolv.net/assets/logos/logo.png"
} }
</script> </script>
@@ -62,7 +62,7 @@
</head> </head>
<body> <body>
<div id="loading" class="centered"> <div id="loading" class="centered">
<img src="https://raw.githubusercontent.com/WerWolv/ImHex/master/plugins/builtin/romfs/assets/dark/banner.svg" id="logo" alt="ImHex Logo"> <img src="https://raw.githubusercontent.com/WerWolv/ImHex/master/plugins/builtin/romfs/assets/dark/banner.png" id="logo" alt="ImHex Logo">
<h1>A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</h1> <h1>A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</h1>
<h2>Available both natively and on the web</h2> <h2>Available both natively and on the web</h2>
<h5>ImHex runs directly in your web browser with the help of Emscripten and WebAssembly.</h5> <h5>ImHex runs directly in your web browser with the help of Emscripten and WebAssembly.</h5>

View File

@@ -10,8 +10,8 @@
], ],
"icons": [ "icons": [
{ {
"src": "icon.svg", "src": "icon.png",
"type": "image/svg", "type": "image/png",
"sizes": "640x640" "sizes": "640x640"
} }
], ],

View File

@@ -57,11 +57,6 @@
<loc>https://web.imhex.werwolv.net?lang=it-IT</loc> <loc>https://web.imhex.werwolv.net?lang=it-IT</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod> <lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url> </url>
<url>
<title>Русский</title>
<loc>https://web.imhex.werwolv.net?lang=ru-RU</loc>
<lastmod>2024-01-02T11:44:00+00:00</lastmod>
</url>
</urlset> </urlset>

View File

@@ -137,7 +137,7 @@ a:hover {
:root { :root {
--progress: 0%; --progress: 25%;
} }
.progress-bar-container { .progress-bar-container {
@@ -175,14 +175,3 @@ a:hover {
width: var(--progress); width: var(--progress);
background-color: #3864cb; background-color: #3864cb;
} }
#logo {
height: 25%;
margin-top: 50px;
}
.canvas-fixed {
position: absolute;
top: 0;
left: 0;
}

View File

@@ -100,77 +100,7 @@ var notWorkingTimer = setTimeout(() => {
var Module = { var Module = {
preRun: [], preRun: [],
postRun: function() { postRun: [],
// Patch the emscripten GLFW module to send mouse and touch events in the right order
// For ImGui interactions to correctly work with touch input, MousePos events need
// to be processed first and then MouseButton events in the next frame. By default,
// GLFW does the exact opposite, which causes buttons to require two taps to register
// and windows get "stuck" to the cursor when dragged or resized
GLFW.onMousemove = event => {
if (event.type === "touchmove") {
event.preventDefault();
let primaryChanged = false;
for (let i of event.changedTouches) {
if (GLFW.primaryTouchId === i.identifier) {
Browser.setMouseCoords(i.pageX, i.pageY);
primaryChanged = true;
break;
}
}
if (!primaryChanged) {
return;
}
} else {
Browser.calculateMouseEvent(event);
}
};
GLFW.onMouseButtonChanged = (event, status) => {
if (!GLFW.active) return;
if (event.target != Module["canvas"]) return;
const isTouchType = event.type === "touchstart" || event.type === "touchend" || event.type === "touchcancel";
let eventButton = 0;
if (isTouchType) {
event.preventDefault();
let primaryChanged = false;
if (GLFW.primaryTouchId === null && event.type === "touchstart" && event.targetTouches.length > 0) {
const chosenTouch = event.targetTouches[0];
GLFW.primaryTouchId = chosenTouch.identifier;
Browser.setMouseCoords(chosenTouch.pageX, chosenTouch.pageY);
primaryChanged = true;
} else if (event.type === "touchend" || event.type === "touchcancel") {
for (let i of event.changedTouches) {
if (GLFW.primaryTouchId === i.identifier) {
GLFW.primaryTouchId = null;
primaryChanged = true;
break;
}
}
}
if (!primaryChanged) {
return;
}
} else {
Browser.calculateMouseEvent(event);
eventButton = GLFW.DOMToGLFWMouseButton(event);
}
if (status == 1) {
GLFW.active.buttons |= (1 << eventButton);
try {
event.target.setCapture();
} catch (e) {}
} else {
GLFW.active.buttons &= ~(1 << eventButton);
}
if (GLFW.active.cursorPosFunc) {
getWasmTableEntry(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY);
}
if (GLFW.active.mouseButtonFunc) {
getWasmTableEntry(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
}
};
},
onRuntimeInitialized: function() { onRuntimeInitialized: function() {
// Triggered when the wasm module is loaded and ready to use. // Triggered when the wasm module is loaded and ready to use.
document.getElementById("loading").style.display = "none" document.getElementById("loading").style.display = "none"
@@ -181,55 +111,13 @@ var Module = {
print: (function() { })(), print: (function() { })(),
printErr: function(text) { }, printErr: function(text) { },
canvas: (function() { canvas: (function() {
const canvas = document.getElementById('canvas'); let canvas = document.getElementById('canvas');
canvas.addEventListener("webglcontextlost", function(e) { // As a default initial behavior, pop up an alert when webgl context is lost. To make your
alert('WebGL context lost, please reload the page'); // application robust, you may want to override this behavior before shipping!
e.preventDefault(); // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
}, false); canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
// Turn long touches into right-clicks return canvas;
let timer = null;
canvas.addEventListener('touchstart', event => {
timer = setTimeout(() => {
let eventArgs = {
bubbles: true,
cancelable: true,
view: window,
screenX: event.touches[0].screenX,
screenY: event.touches[0].screenY,
clientX: event.touches[0].clientX,
clientY: event.touches[0].clientY,
button: 2,
buttons: 2,
relatedTarget: event.target,
region: event.region
}
canvas.dispatchEvent(new MouseEvent('mousedown', eventArgs));
canvas.dispatchEvent(new MouseEvent('mouseup', eventArgs));
}, 400);
});
canvas.addEventListener('touchend', event => {
if (timer) {
clearTimeout(timer);
timer = null;
}
});
if (typeof WebGL2RenderingContext !== 'undefined') {
let gl = canvas.getContext('webgl2', { stencil: true });
if (!gl) {
console.error('WebGL 2 not available, falling back to WebGL');
gl = canvas.getContext('webgl', { stencil: true });
}
if (!gl) {
alert('WebGL not available with stencil buffer');
}
return canvas;
} else {
alert('WebGL 2 not supported by this browser');
}
})(), })(),
setStatus: function(text) { }, setStatus: function(text) { },
totalDependencies: 0, totalDependencies: 0,
@@ -256,16 +144,14 @@ if (urlParams.has("lang")) {
window.addEventListener('resize', js_resizeCanvas, false); window.addEventListener('resize', js_resizeCanvas, false);
function js_resizeCanvas() { function js_resizeCanvas() {
let canvas = document.getElementById('canvas'); let canvas = document.getElementById('canvas');
canvas.top = document.documentElement.clientTop;
canvas.left = document.documentElement.clientLeft;
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0); canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);
canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0); canvas.height = Math.min(document.documentElement.clientHeight, window.innerHeight || 0);
}
// Prevent some default browser shortcuts from preventing ImHex ones to work canvas.classList.add("canvas_full_screen")
document.addEventListener('keydown', e => {
if (e.ctrlKey) { if (GLFW.active && GLFW.active.windowPosFunc) {
if (e.which == 83) e.preventDefault(); getWasmTableEntry(GLFW.active.windowPosFunc)(GLFW.active.id, GLFW.active.x, GLFW.active.y);
} }
})
GLFW.onWindowSizeChanged();
}

View File

@@ -22,9 +22,6 @@ set(LIBIMHEX_SOURCES
source/data_processor/link.cpp source/data_processor/link.cpp
source/data_processor/node.cpp source/data_processor/node.cpp
source/project/project.cpp
source/project/project_manager.cpp
source/helpers/utils.cpp source/helpers/utils.cpp
source/helpers/utils_linux.cpp source/helpers/utils_linux.cpp
source/helpers/fs.cpp source/helpers/fs.cpp
@@ -39,10 +36,6 @@ set(LIBIMHEX_SOURCES
source/helpers/logger.cpp source/helpers/logger.cpp
source/helpers/tar.cpp source/helpers/tar.cpp
source/helpers/debugging.cpp source/helpers/debugging.cpp
source/helpers/default_paths.cpp
source/helpers/imgui_hooks.cpp
source/helpers/semantic_version.cpp
source/helpers/keys.cpp
source/test/tests.cpp source/test/tests.cpp
@@ -54,7 +47,6 @@ set(LIBIMHEX_SOURCES
source/ui/view.cpp source/ui/view.cpp
source/ui/popup.cpp source/ui/popup.cpp
source/ui/toast.cpp source/ui/toast.cpp
source/ui/banner.cpp
source/subcommands/subcommands.cpp source/subcommands/subcommands.cpp
) )
@@ -126,41 +118,31 @@ setupCompilerFlags(libimhex)
include(GenerateExportHeader) include(GenerateExportHeader)
generate_export_header(libimhex) generate_export_header(libimhex)
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS}) target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} include ${XDGPP_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ${MAGIC_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS} ${FMT_INCLUDE_DIRS} ${LIBBACKTRACE_INCLUDE_DIRS})
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${CURL_LIBRARIES})
endif()
if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD) if (NOT IMHEX_EXTERNAL_PLUGIN_BUILD)
if (WIN32) if (WIN32)
set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) set_target_properties(libimhex PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
if (NOT MSVC) target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
target_link_options(libimhex PRIVATE -Wl,--export-all-symbols)
endif()
target_link_libraries(libimhex PRIVATE Netapi32.lib)
target_compile_definitions(libimhex PRIVATE EXPORT_SYMBOLS=1)
elseif (APPLE) elseif (APPLE)
find_library(FOUNDATION NAMES Foundation) find_library(FOUNDATION NAMES Foundation)
target_link_libraries(libimhex PUBLIC ${FOUNDATION}) target_link_libraries(libimhex PUBLIC ${FOUNDATION})
endif () endif ()
target_link_libraries(libimhex PRIVATE libpl microtar ${NFD_LIBRARIES} magic) target_link_libraries(libimhex PRIVATE microtar libwolv ${NFD_LIBRARIES} magic dl ${JTHREAD_LIBRARIES})
target_link_libraries(libimhex PUBLIC libwolv libpl_includes libpl-gen ${IMGUI_LIBRARIES} ${JTHREAD_LIBRARIES}) target_link_libraries(libimhex PUBLIC libpl ${IMGUI_LIBRARIES})
if (NOT WIN32)
target_link_libraries(libimhex PRIVATE dl)
endif()
if (NOT EMSCRIPTEN)
# curl is only used in non-emscripten builds
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} CURL::libcurl)
endif()
target_include_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_INCLUDE_DIR} ${LIBBACKTRACE_INCLUDE_DIRS} ${MAGIC_INCLUDE_DIRS})
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARIES})
target_link_directories(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${MBEDTLS_LIBRARY_DIR} ${MAGIC_LIBRARY_DIRS})
precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include") precompileHeaders(libimhex "${CMAKE_CURRENT_SOURCE_DIR}/include")
endif() endif()
target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} ${BOOST_LIBRARIES}) target_link_libraries(libimhex ${LIBIMHEX_LIBRARY_TYPE} ${NLOHMANN_JSON_LIBRARIES} imgui_all_includes ${MBEDTLS_LIBRARIES} ${FMT_LIBRARIES} ${LUNASVG_LIBRARIES} tracing)
set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE) set_property(TARGET libimhex PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)

View File

@@ -1,3 +1,4 @@
#pragma once #pragma once
#include <hex/helpers/types.hpp> #include <hex/helpers/types.hpp>
#include <hex/helpers/intrinsics.hpp>

View File

@@ -14,7 +14,6 @@
#include <imgui.h> #include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h> #include <hex/ui/imgui_imhex_extensions.h>
#include <hex/api/localization_manager.hpp> #include <hex/api/localization_manager.hpp>
#include <hex/helpers/auto_reset.hpp>
namespace hex { namespace hex {
@@ -296,7 +295,6 @@ namespace hex {
}; };
class AchievementManager { class AchievementManager {
static bool s_initialized;
public: public:
AchievementManager() = delete; AchievementManager() = delete;
@@ -362,7 +360,7 @@ namespace hex {
* @brief Returns all registered achievements * @brief Returns all registered achievements
* @return All achievements * @return All achievements
*/ */
static const std::unordered_map<UnlocalizedString, std::unordered_map<UnlocalizedString, std::unique_ptr<Achievement>>>& getAchievements(); static const std::unordered_map<std::string, std::unordered_map<std::string, std::unique_ptr<Achievement>>>& getAchievements();
/** /**
* @brief Returns all achievement start nodes * @brief Returns all achievement start nodes
@@ -370,14 +368,14 @@ namespace hex {
* @param rebuild Whether to rebuild the list of start nodes * @param rebuild Whether to rebuild the list of start nodes
* @return All achievement start nodes * @return All achievement start nodes
*/ */
static const std::unordered_map<UnlocalizedString, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true); static const std::unordered_map<std::string, std::vector<AchievementNode*>>& getAchievementStartNodes(bool rebuild = true);
/** /**
* @brief Returns all achievement nodes * @brief Returns all achievement nodes
* @param rebuild Whether to rebuild the list of nodes * @param rebuild Whether to rebuild the list of nodes
* @return All achievement nodes * @return All achievement nodes
*/ */
static const std::unordered_map<UnlocalizedString, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true); static const std::unordered_map<std::string, std::list<AchievementNode>>& getAchievementNodes(bool rebuild = true);
/** /**
* @brief Loads the progress of all achievements from the achievements save file * @brief Loads the progress of all achievements from the achievements save file

View File

@@ -2,10 +2,10 @@
#include <hex.hpp> #include <hex.hpp>
#include <hex/api/localization_manager.hpp> #include <hex/api/localization_manager.hpp>
#include <hex/api/shortcut_manager.hpp>
#include <hex/helpers/concepts.hpp> #include <hex/helpers/concepts.hpp>
#include <functional> #include <functional>
#include <map>
#include <mutex> #include <mutex>
#include <span> #include <span>
#include <string> #include <string>
@@ -20,11 +20,11 @@ using ImGuiDataType = int;
using ImGuiInputTextFlags = int; using ImGuiInputTextFlags = int;
struct ImColor; struct ImColor;
enum ImGuiCustomCol : int; enum ImGuiCustomCol : int;
typedef int ImGuiColorEditFlags;
namespace hex { namespace hex {
class View; class View;
class Shortcut;
class Task; class Task;
namespace dp { namespace dp {
@@ -44,6 +44,7 @@ namespace hex {
plugins when needed. plugins when needed.
*/ */
namespace ContentRegistry { namespace ContentRegistry {
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */ /* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
namespace Settings { namespace Settings {
@@ -177,7 +178,7 @@ namespace hex {
class SliderDataSize : public Widget { class SliderDataSize : public Widget {
public: public:
SliderDataSize(u64 defaultValue, u64 min, u64 max, u64 stepSize) : m_value(defaultValue), m_min(min), m_max(max), m_stepSize(stepSize) { } SliderDataSize(u64 defaultValue, u64 min, u64 max) : m_value(defaultValue), m_min(min), m_max(max) { }
bool draw(const std::string &name) override; bool draw(const std::string &name) override;
void load(const nlohmann::json &data) override; void load(const nlohmann::json &data) override;
@@ -188,12 +189,11 @@ namespace hex {
protected: protected:
u64 m_value; u64 m_value;
u64 m_min, m_max; u64 m_min, m_max;
u64 m_stepSize;
}; };
class ColorPicker : public Widget { class ColorPicker : public Widget {
public: public:
explicit ColorPicker(ImColor defaultColor, ImGuiColorEditFlags flags = 0); explicit ColorPicker(ImColor defaultColor);
bool draw(const std::string &name) override; bool draw(const std::string &name) override;
@@ -203,14 +203,12 @@ namespace hex {
[[nodiscard]] ImColor getColor() const; [[nodiscard]] ImColor getColor() const;
protected: protected:
std::array<float, 4> m_value = {}, m_defaultValue = {}; std::array<float, 4> m_value{};
ImGuiColorEditFlags m_flags;
}; };
class DropDown : public Widget { class DropDown : public Widget {
public: public:
explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items.begin(), items.end()), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { } explicit DropDown(const std::vector<std::string> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
explicit DropDown(const std::vector<UnlocalizedString> &items, const std::vector<nlohmann::json> &settingsValues, const nlohmann::json &defaultItem) : m_items(items), m_settingsValues(settingsValues), m_defaultItem(defaultItem) { }
bool draw(const std::string &name) override; bool draw(const std::string &name) override;
@@ -221,7 +219,7 @@ namespace hex {
const nlohmann::json& getValue() const; const nlohmann::json& getValue() const;
protected: protected:
std::vector<UnlocalizedString> m_items; std::vector<std::string> m_items;
std::vector<nlohmann::json> m_settingsValues; std::vector<nlohmann::json> m_settingsValues;
nlohmann::json m_defaultItem; nlohmann::json m_defaultItem;
@@ -328,7 +326,7 @@ namespace hex {
result = defaultValue; result = defaultValue;
return result.get<T>(); return result.get<T>();
} catch (const nlohmann::json::exception &) { } catch (const nlohmann::json::exception &e) {
return defaultValue; return defaultValue;
} }
} }
@@ -383,7 +381,7 @@ namespace hex {
}; };
using DisplayCallback = std::function<std::string(std::string)>; using DisplayCallback = std::function<std::string(std::string)>;
using ExecuteCallback = std::function<std::optional<std::string>(std::string)>; using ExecuteCallback = std::function<void(std::string)>;
using QueryCallback = std::function<std::vector<QueryResult>(std::string)>; using QueryCallback = std::function<std::vector<QueryResult>(std::string)>;
struct Entry { struct Entry {
@@ -419,7 +417,7 @@ namespace hex {
const std::string &command, const std::string &command,
const UnlocalizedString &unlocalizedDescription, const UnlocalizedString &unlocalizedDescription,
const impl::DisplayCallback &displayCallback, const impl::DisplayCallback &displayCallback,
const impl::ExecuteCallback &executeCallback = [](auto) { return std::nullopt; }); const impl::ExecuteCallback &executeCallback = [](auto) {});
/** /**
* @brief Adds a new command handler to the command palette * @brief Adds a new command handler to the command palette
@@ -440,7 +438,7 @@ namespace hex {
namespace impl { namespace impl {
using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, bool, std::span<const pl::core::Token::Literal>)>; using VisualizerFunctionCallback = std::function<void(pl::ptrn::Pattern&, pl::ptrn::IIterable&, bool, std::span<const pl::core::Token::Literal>)>;
struct FunctionDefinition { struct FunctionDefinition {
pl::api::Namespace ns; pl::api::Namespace ns;
@@ -452,14 +450,6 @@ namespace hex {
bool dangerous; bool dangerous;
}; };
struct TypeDefinition {
pl::api::Namespace ns;
std::string name;
pl::api::FunctionParameterCount parameterCount;
pl::api::TypeCallback callback;
};
struct Visualizer { struct Visualizer {
pl::api::FunctionParameterCount parameterCount; pl::api::FunctionParameterCount parameterCount;
VisualizerFunctionCallback callback; VisualizerFunctionCallback callback;
@@ -469,7 +459,6 @@ namespace hex {
const std::map<std::string, Visualizer>& getInlineVisualizers(); const std::map<std::string, Visualizer>& getInlineVisualizers();
const std::map<std::string, pl::api::PragmaHandler>& getPragmas(); const std::map<std::string, pl::api::PragmaHandler>& getPragmas();
const std::vector<FunctionDefinition>& getFunctions(); const std::vector<FunctionDefinition>& getFunctions();
const std::vector<TypeDefinition>& getTypes();
} }
@@ -528,20 +517,6 @@ namespace hex {
const pl::api::FunctionCallback &func const pl::api::FunctionCallback &func
); );
/**
* @brief Adds a new type to the pattern language
* @param ns The namespace of the type
* @param name The name of the type
* @param parameterCount The amount of non-type template parameters the type takes
* @param func The type callback
*/
void addType(
const pl::api::Namespace &ns,
const std::string &name,
pl::api::FunctionParameterCount parameterCount,
const pl::api::TypeCallback &func
);
/** /**
* @brief Adds a new visualizer to the pattern language * @brief Adds a new visualizer to the pattern language
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data * @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
@@ -576,7 +551,7 @@ namespace hex {
namespace impl { namespace impl {
void add(std::unique_ptr<View> &&view); void add(std::unique_ptr<View> &&view);
const std::map<UnlocalizedString, std::unique_ptr<View>>& getEntries(); const std::map<std::string, std::unique_ptr<View>>& getEntries();
} }
@@ -597,12 +572,6 @@ namespace hex {
* @return The view if it exists, nullptr otherwise * @return The view if it exists, nullptr otherwise
*/ */
View* getViewByName(const UnlocalizedString &unlocalizedName); View* getViewByName(const UnlocalizedString &unlocalizedName);
/**
* @brief Gets the currently focused view
* @return The view that is focused right now. nullptr if none is focused
*/
View* getFocusedView();
} }
/* Tools Registry. Allows adding new entries to the tools window */ /* Tools Registry. Allows adding new entries to the tools window */
@@ -632,7 +601,8 @@ namespace hex {
/* Data Inspector Registry. Allows adding of new types to the data inspector */ /* Data Inspector Registry. Allows adding of new types to the data inspector */
namespace DataInspector { namespace DataInspector {
enum class NumberDisplayStyle : u8 { enum class NumberDisplayStyle
{
Decimal, Decimal,
Hexadecimal, Hexadecimal,
Octal Octal
@@ -686,13 +656,6 @@ namespace hex {
std::optional<impl::EditingFunction> editingFunction = std::nullopt std::optional<impl::EditingFunction> editingFunction = std::nullopt
); );
/**
* @brief Allows adding new menu items to data inspector row context menus. Call this function inside the
* draw function of the data inspector row definition.
* @param function Callback that will draw menu items
*/
void drawMenuItems(const std::function<void()> &function);
} }
/* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */ /* Data Processor Node Registry. Allows adding new processor nodes to be used in the data processor */
@@ -727,7 +690,7 @@ namespace hex {
add(impl::Entry { add(impl::Entry {
unlocalizedCategory, unlocalizedCategory,
unlocalizedName, unlocalizedName,
[=, ...args = std::forward<Args>(args)]() mutable { [=, ...args = std::forward<Args>(args)] mutable {
auto node = std::make_unique<T>(std::forward<Args>(args)...); auto node = std::make_unique<T>(std::forward<Args>(args)...);
node->setUnlocalizedName(unlocalizedName); node->setUnlocalizedName(unlocalizedName);
return node; return node;
@@ -785,7 +748,7 @@ namespace hex {
struct MenuItem { struct MenuItem {
std::vector<UnlocalizedString> unlocalizedNames; std::vector<UnlocalizedString> unlocalizedNames;
Icon icon; Icon icon;
Shortcut shortcut; std::unique_ptr<Shortcut> shortcut;
View *view; View *view;
MenuCallback callback; MenuCallback callback;
EnabledCallback enabledCallback; EnabledCallback enabledCallback;
@@ -811,7 +774,6 @@ namespace hex {
const std::multimap<u32, MainMenuItem>& getMainMenuItems(); const std::multimap<u32, MainMenuItem>& getMainMenuItems();
const std::multimap<u32, MenuItem>& getMenuItems(); const std::multimap<u32, MenuItem>& getMenuItems();
const std::vector<MenuItem*>& getToolbarMenuItems();
std::multimap<u32, MenuItem>& getMenuItemsMutable(); std::multimap<u32, MenuItem>& getMenuItemsMutable();
const std::vector<DrawCallback>& getWelcomeScreenEntries(); const std::vector<DrawCallback>& getWelcomeScreenEntries();
@@ -954,11 +916,6 @@ namespace hex {
*/ */
void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color); void addMenuItemToToolbar(const UnlocalizedString &unlocalizedName, ImGuiCustomCol color);
/**
* @brief Reconstructs the toolbar items list after they have been modified
*/
void updateToolbarItems();
/** /**
* @brief Adds a new sidebar item * @brief Adds a new sidebar item
* @param icon The icon to use for the item * @param icon The icon to use for the item
@@ -1008,7 +965,7 @@ namespace hex {
void add(bool addToList = true) { void add(bool addToList = true) {
auto typeName = T().getTypeName(); auto typeName = T().getTypeName();
impl::add(typeName, []() -> std::unique_ptr<prv::Provider> { impl::add(typeName, [] -> std::unique_ptr<prv::Provider> {
return std::make_unique<T>(); return std::make_unique<T>();
}); });
@@ -1023,35 +980,13 @@ namespace hex {
namespace impl { namespace impl {
using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size, bool preview)>; using Callback = std::function<std::string(prv::Provider *provider, u64 address, size_t size)>;
struct ExportMenuEntry { struct Entry {
UnlocalizedString unlocalizedName; UnlocalizedString unlocalizedName;
Callback callback; Callback callback;
}; };
struct FindOccurrence { const std::vector<Entry>& getEntries();
Region region;
enum class DecodeType { ASCII, UTF8, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native;
bool selected;
};
using FindExporterCallback = std::function<std::vector<u8>(const std::vector<FindOccurrence>&, std::function<std::string(FindOccurrence)>)>;
struct FindExporterEntry {
UnlocalizedString unlocalizedName;
std::string fileExtension;
FindExporterCallback callback;
};
/**
* @brief Retrieves a list of all registered data formatters used by the 'File -> Export' menu
*/
const std::vector<ExportMenuEntry>& getExportMenuEntries();
/**
* @brief Retrieves a list of all registered data formatters used in the Results section of the 'Find' view
*/
const std::vector<FindExporterEntry>& getFindExporterEntries();
} }
@@ -1061,14 +996,7 @@ namespace hex {
* @param unlocalizedName The unlocalized name of the formatter * @param unlocalizedName The unlocalized name of the formatter
* @param callback The function to call to format the data * @param callback The function to call to format the data
*/ */
void addExportMenuEntry(const UnlocalizedString &unlocalizedName, const impl::Callback &callback); void add(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
/**
* @brief Adds a new data exporter for Find results
* @param unlocalizedName The unlocalized name of the formatter
* @param callback The function to call to format the data
*/
void addFindExportFormatter(const UnlocalizedString &unlocalizedName, const std::string fileExtension, const impl::FindExporterCallback &callback);
} }
@@ -1116,9 +1044,9 @@ namespace hex {
[[nodiscard]] const UnlocalizedString& getUnlocalizedName() const { return m_unlocalizedName; } [[nodiscard]] const UnlocalizedString& getUnlocalizedName() const { return m_unlocalizedName; }
[[nodiscard]] static int DefaultTextInputFlags();
protected: protected:
const static int TextInputFlags;
bool drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const; bool drawDefaultScalarEditingTextBox(u64 address, const char *format, ImGuiDataType dataType, u8 *data, ImGuiInputTextFlags flags) const;
bool drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const; bool drawDefaultTextEditingTextBox(u64 address, std::string &data, ImGuiInputTextFlags flags) const;
@@ -1129,7 +1057,7 @@ namespace hex {
}; };
struct MiniMapVisualizer { struct MiniMapVisualizer {
using Callback = std::function<void(u64, std::span<const u8>, std::vector<ImColor>&)>; using Callback = std::function<ImColor(const std::vector<u8>&)>;
UnlocalizedString unlocalizedName; UnlocalizedString unlocalizedName;
Callback callback; Callback callback;
@@ -1310,7 +1238,7 @@ namespace hex {
void stopServices(); void stopServices();
} }
void registerService(const UnlocalizedString &unlocalizedString, const impl::Callback &callback); void registerService(const UnlocalizedString &unlocalizedName, const impl::Callback &callback);
} }
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */ /* Network Communication Interface Registry. Allows adding new communication interface endpoints */
@@ -1369,7 +1297,6 @@ namespace hex {
} }
/* Data Information Registry. Allows adding new analyzers to the data information view */
namespace DataInformation { namespace DataInformation {
class InformationSection { class InformationSection {
@@ -1436,54 +1363,6 @@ namespace hex {
} }
/* Disassembler Registry. Allows adding new disassembler architectures */
namespace Disassembler {
struct Instruction {
u64 address;
u64 offset;
size_t size;
std::string bytes;
std::string mnemonic;
std::string operators;
};
class Architecture {
public:
explicit Architecture(std::string name) : m_name(std::move(name)) {}
virtual ~Architecture() = default;
virtual bool start() = 0;
virtual void end() = 0;
virtual std::optional<Instruction> disassemble(u64 imageBaseAddress, u64 instructionLoadAddress, u64 instructionDataAddress, std::span<const u8> code) = 0;
virtual void drawSettings() = 0;
[[nodiscard]] const std::string& getName() const { return m_name; }
private:
std::string m_name;
};
namespace impl {
using CreatorFunction = std::function<std::unique_ptr<Architecture>()>;
void addArchitectureCreator(CreatorFunction function);
const std::map<std::string, CreatorFunction>& getArchitectures();
}
template<std::derived_from<Architecture> T>
void add(auto && ...args) {
impl::addArchitectureCreator([...args = std::move(args)] {
return std::make_unique<T>(args...);
});
}
}
} }
} }

View File

@@ -14,23 +14,32 @@
#include <wolv/types/type_name.hpp> #include <wolv/types/type_name.hpp>
#define EVENT_DEF_IMPL(event_name, event_name_string, should_log, ...) \ #define EVENT_DEF_IMPL(event_name, event_name_string, should_log, ...) \
struct event_name final : public hex::impl::Event<__VA_ARGS__> { \ struct event_name final : public hex::impl::Event<__VA_ARGS__> { \
constexpr static auto Id = [] { return hex::impl::EventId(event_name_string); }(); \ constexpr static auto Id = [] { return hex::impl::EventId(event_name_string); }(); \
constexpr static auto ShouldLog = (should_log); \ constexpr static auto ShouldLog = (should_log); \
explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \ explicit event_name(Callback func) noexcept : Event(std::move(func)) { } \
\ \
static EventManager::EventList::iterator subscribe(Event::Callback function) { return EventManager::subscribe<event_name>(std::move(function)); } \ static EventManager::EventList::iterator subscribe(Event::Callback function) { return EventManager::subscribe<event_name>(function); } \
static void subscribe(void *token, Event::Callback function) { EventManager::subscribe<event_name>(token, std::move(function)); } \ static void subscribe(void *token, Event::Callback function) { EventManager::subscribe<event_name>(token, function); } \
static void unsubscribe(const EventManager::EventList::iterator &token) noexcept { EventManager::unsubscribe(token); } \ static void unsubscribe(const EventManager::EventList::iterator &token) noexcept { EventManager::unsubscribe(token); } \
static void unsubscribe(void *token) noexcept { EventManager::unsubscribe<event_name>(token); } \ static void unsubscribe(void *token) noexcept { EventManager::unsubscribe<event_name>(token); } \
static void post(auto &&...args) { EventManager::post<event_name>(std::forward<decltype(args)>(args)...); } \ static void post(auto &&...args) { EventManager::post<event_name>(std::forward<decltype(args)>(args)...); } \
} };
#define EVENT_DEF(event_name, ...) EVENT_DEF_IMPL(event_name, #event_name, true, __VA_ARGS__) #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__) #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;
class View;
}
namespace pl::ptrn { class Pattern; }
namespace hex { namespace hex {
namespace impl { namespace impl {
@@ -49,10 +58,6 @@ namespace hex {
return m_hash == other.m_hash; return m_hash == other.m_hash;
} }
constexpr auto operator<=>(const EventId &other) const {
return m_hash <=> other.m_hash;
}
private: private:
u32 m_hash; u32 m_hash;
}; };
@@ -68,12 +73,11 @@ namespace hex {
explicit Event(Callback func) noexcept : m_func(std::move(func)) { } explicit Event(Callback func) noexcept : m_func(std::move(func)) { }
template<typename E> void operator()(std::string_view eventName, Params... params) const {
void call(Params... params) const {
try { try {
m_func(params...); m_func(params...);
} catch (const std::exception &e) { } catch (const std::exception &e) {
log::error("An exception occurred while handling event {}: {}", wolv::type::getTypeName<E>(), e.what()); log::error("An exception occurred while handling event {}: {}", eventName, e.what());
throw; throw;
} }
} }
@@ -90,12 +94,11 @@ namespace hex {
/** /**
* @brief The EventManager allows subscribing to and posting events to different parts of the program. * @brief The EventManager allows subscribing to and posting events to different parts of the program.
* To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters. * To create a new event, use the EVENT_DEF macro. This will create a new event type with the given name and parameters
* Events should be created in an `events_*.hpp` category file under the `events` folder, and never directly here.
*/ */
class EventManager { class EventManager {
public: public:
using EventList = std::multimap<impl::EventId, std::unique_ptr<impl::EventBase>>; using EventList = std::list<std::pair<impl::EventId, std::unique_ptr<impl::EventBase>>>;
/** /**
* @brief Subscribes to an event * @brief Subscribes to an event
@@ -108,7 +111,7 @@ namespace hex {
std::scoped_lock lock(getEventMutex()); std::scoped_lock lock(getEventMutex());
auto &events = getEvents(); auto &events = getEvents();
return events.insert({ E::Id, std::make_unique<E>(function) }); return events.insert(events.end(), std::make_pair(E::Id, std::make_unique<E>(function)));
} }
/** /**
@@ -121,9 +124,15 @@ namespace hex {
static void subscribe(void *token, typename E::Callback function) { static void subscribe(void *token, typename E::Callback function) {
std::scoped_lock lock(getEventMutex()); std::scoped_lock lock(getEventMutex());
if (isAlreadyRegistered(token, E::Id)) { if (getTokenStore().contains(token)) {
log::fatal("The token '{}' has already registered the same event ('{}')", token, wolv::type::getTypeName<E>()); auto&& [begin, end] = getTokenStore().equal_range(token);
return; const auto eventRegistered = std::any_of(begin, end, [&](auto &item) {
return item.second->first == E::Id;
});
if (eventRegistered) {
log::fatal("The token '{}' has already registered the same event ('{}')", token, wolv::type::getTypeName<E>());
return;
}
} }
getTokenStore().insert({ token, subscribe<E>(function) }); getTokenStore().insert({ token, subscribe<E>(function) });
@@ -148,7 +157,16 @@ namespace hex {
static void unsubscribe(void *token) noexcept { static void unsubscribe(void *token) noexcept {
std::scoped_lock lock(getEventMutex()); std::scoped_lock lock(getEventMutex());
unsubscribe(token, E::Id); 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 != tokenStore.end()) {
getEvents().remove(*iter->second);
tokenStore.erase(iter);
}
} }
/** /**
@@ -160,14 +178,14 @@ namespace hex {
static void post(auto && ...args) { static void post(auto && ...args) {
std::scoped_lock lock(getEventMutex()); std::scoped_lock lock(getEventMutex());
auto [begin, end] = getEvents().equal_range(E::Id); for (const auto &[id, event] : getEvents()) {
for (auto it = begin; it != end; ++it) { if (id == E::Id) {
const auto &[id, event] = *it; (*static_cast<E *const>(event.get()))(wolv::type::getTypeName<E>(), std::forward<decltype(args)>(args)...);
(*static_cast<E *const>(event.get())).template call<E>(std::forward<decltype(args)>(args)...); }
} }
#if defined (DEBUG) #if defined (DEBUG)
if constexpr (E::ShouldLog) if (E::ShouldLog)
log::debug("Event posted: '{}'", wolv::type::getTypeName<E>()); log::debug("Event posted: '{}'", wolv::type::getTypeName<E>());
#endif #endif
} }
@@ -186,9 +204,116 @@ namespace hex {
static std::multimap<void *, EventList::iterator>& getTokenStore(); static std::multimap<void *, EventList::iterator>& getTokenStore();
static EventList& getEvents(); static EventList& getEvents();
static std::recursive_mutex& getEventMutex(); static std::recursive_mutex& getEventMutex();
static bool isAlreadyRegistered(void *token, impl::EventId id);
static void unsubscribe(void *token, impl::EventId id);
}; };
/* Default Events */
/**
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
*/
EVENT_DEF(EventImHexStartupFinished);
EVENT_DEF(EventFileLoaded, std::fs::path);
EVENT_DEF(EventDataChanged, prv::Provider *);
EVENT_DEF(EventHighlightingChanged);
EVENT_DEF(EventWindowClosing, GLFWwindow *);
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
EVENT_DEF(EventAbnormalTermination, int);
EVENT_DEF(EventThemeChanged);
EVENT_DEF(EventOSThemeChanged);
EVENT_DEF(EventWindowFocused, bool);
/**
* @brief Called when the provider is created.
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
* (although the event can also be called manually without problem)
*/
EVENT_DEF(EventProviderCreated, prv::Provider *);
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
/**
* @brief Called as a continuation of EventProviderCreated
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
* If skipLoadInterface failed, this event is not called
*
* @note this is not related to Provider::open()
*/
EVENT_DEF(EventProviderOpened, prv::Provider *);
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
EVENT_DEF(EventProviderClosed, prv::Provider *);
EVENT_DEF(EventProviderDeleted, prv::Provider *);
EVENT_DEF(EventProviderSaved, prv::Provider *);
EVENT_DEF(EventWindowInitialized);
EVENT_DEF(EventWindowDeinitializing, GLFWwindow *);
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&);
EVENT_DEF(EventSearchBoxClicked, u32);
EVENT_DEF(EventViewOpened, View*);
EVENT_DEF(EventFirstLaunch);
EVENT_DEF(EventFileDragged, bool);
EVENT_DEF(EventFileDropped, std::fs::path);
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
/**
* @brief Called when a project has been loaded
*/
EVENT_DEF(EventProjectOpened);
EVENT_DEF_NO_LOG(EventFrameBegin);
EVENT_DEF_NO_LOG(EventFrameEnd);
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
EVENT_DEF(RequestOpenWindow, std::string);
EVENT_DEF(RequestHexEditorSelectionChange, Region);
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
EVENT_DEF(RequestRemoveBookmark, u64);
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
EVENT_DEF(RequestRunPatternCode);
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
EVENT_DEF(RequestUpdateWindowTitle);
EVENT_DEF(RequestCloseImHex, bool);
EVENT_DEF(RequestRestartImHex);
EVENT_DEF(RequestOpenFile, std::fs::path);
EVENT_DEF(RequestChangeTheme, std::string);
EVENT_DEF(RequestOpenPopup, std::string);
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
/**
* @brief Creates a provider from it's unlocalized name, and add it to the provider list
*/
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
EVENT_DEF(RequestInitThemeHandlers);
/**
* @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 *);
/**
* Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
*/
EVENT_DEF(EventCrashRecovered, const std::exception &);
} }

View File

@@ -1,120 +0,0 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* Forward declarations */
struct GLFWwindow;
namespace hex { class View; }
/* GUI events definitions */
namespace hex {
/**
* @brief Signals a newly opened window
*
* This event is sent when the window has just been opened and docked by the Window manager.
*
* FIXME: In the event that a newly created window is already docked, this will not be sent.
*
* FIXME: This is currently only used for the introduction tutorial.
* If the event's only purpose is this, maybe rename it?
*
* @param view the new view reference
*/
EVENT_DEF(EventViewOpened, View*);
/**
* @brief Signals a change in the DPI scale.
*
* This event is called once at startup to signal native scale definition (by passing the same value twice).
* On Windows OS, this event can also be posted if the window DPI has been changed.
*
* @param oldScale the old scale
* @param newScale the current scale that's now in use
*/
EVENT_DEF(EventDPIChanged, float, float);
/**
* @brief Signals the focus of the ImHex main window.
*
* This is directly tied as a GLFW window focus callback, and will be called accordingly when GLFW detects
* a change in focus.
*
* @param isFocused true if the window is focused
*/
EVENT_DEF(EventWindowFocused, bool);
/**
* @brief Signals a window being closed.
*
* Allows reactive clean up of running tasks, and prevents ImHex from closing
* by displaying an exit confirmation popup.
*
* @param window The window reference
*/
EVENT_DEF(EventWindowClosing, GLFWwindow*);
/**
* @brief Informs that the main window is initialized
*
* On Windows OS, it is used to initialize system theme, if ImHex's theme is following it.
*
* FIXME: Change event name to reflect Theme detection, if it's only used for that purpose?
*/
EVENT_DEF(EventWindowInitialized);
/**
* @brief Informs that the main window is deinitializing
*
* Allows for lifecycle cleanup before ImHex shutdown.
*
* @param window The window reference
*/
EVENT_DEF(EventWindowDeinitializing, GLFWwindow*);
/**
* @brief Signals a theme change in the host OS
*
* Allows ImHex to react to OS theme changes dynamically during execution.
*/
EVENT_DEF(EventOSThemeChanged);
}
/* silent (no-logging) GUI events definitions */
namespace hex {
/**
* @brief Signals the start of a new ImGui frame
*/
EVENT_DEF_NO_LOG(EventFrameBegin);
/**
* @brief Signals the end of an ImGui frame
*/
EVENT_DEF_NO_LOG(EventFrameEnd);
/**
* @brief Windows OS: Sets the taskbar icon state
*
* This event is used on Windows OS to display progress through the taskbar icon (the famous "green loading bar"
* in the taskbar).
*
* @param progressState the progress state (converted from the TaskProgressState enum)
* @param progressType the type of progress (converted from the TaskProgressType enum)
* @param percentage actual progress percentage (expected from 0 to 100)
*
* @see hex::ImHexApi::System::TaskProgressState
* @see hex::ImHexApi::System::TaskProgressType
*/
EVENT_DEF_NO_LOG(EventSetTaskBarIconState, u32, u32, u32);
/**
* @brief Informs of an ImGui element being rendered
*
* @param elementId the element's ID
* @param boundingBox the bounding box (composed of 4 floats)
*/
EVENT_DEF_NO_LOG(EventImGuiElementRendered, ImGuiID, const std::array<float, 4>&);
}

View File

@@ -1,158 +0,0 @@
#pragma once
#include <hex/api/event_manager.hpp>
#include <hex/helpers/patches.hpp>
/* Forward declarations */
namespace hex { class Achievement; }
/* Interaction events definitions */
namespace hex {
/**
* @brief Signals a file was loaded
*
* FIXME: this event is unused and should be scrapped.
*
* @param path the loaded file's path
*/
EVENT_DEF(EventFileLoaded, std::fs::path);
/**
* @brief Signals a change in the current data
*
* Enables provider reaction to data change, especially the data inspector.
*
* This is caused by the following:
* - an explicit provider reload, requested by the user (Ctrl+R)
* - any user action that results in the creation of an "undo" stack action (generally a data modification)
*
* @param provider the Provider subject to the data change
*/
EVENT_DEF(EventDataChanged, prv::Provider *);
/**
* @brief Signals a change in highlighting
*
* The event's only purpose is for the Hex editor to clear highlights when receiving this event.
*/
EVENT_DEF(EventHighlightingChanged);
/**
* @brief Informs of a provider region being selected
*
* This is very generally used to signal user actions that select a specific region within the provider.
* It is also used to pass on regions when the provider changes.
*
* @param providerRegion the provider-aware region being selected
*/
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);
/**
* @brief Signals a theme change
*
* On Windows OS, this is used to reflect the theme color onto the window frame.
*/
EVENT_DEF(EventThemeChanged);
/**
* @brief Signals that a bookmark was created
*
* For now, this event's only purpose is to unlock an achievement.
*
* @param entry the new bookmark
*/
EVENT_DEF(EventBookmarkCreated, ImHexApi::Bookmarks::Entry&);
/**
* @brief Called upon creation of an IPS patch.
* As for now, the event only serves a purpose for the achievement unlock.
*
* @param data the pointer to the patch content's start
* @param size the patch data size
* @param kind the patch's kind
*/
EVENT_DEF(EventPatchCreated, const u8*, u64, const PatchKind);
/**
* @brief Signals the beginning of evaluation of the current pattern
*
* This allows resetting the drawer view for the pattern data while we wait for the execution completion.
*/
EVENT_DEF(EventPatternEvaluating);
/**
* @brief Signals the completion of the pattern evaluation
*
* This causes another reset in the drawer view, to refresh the table displayed to the user.
*
* @param code the execution's status code
*/
EVENT_DEF(EventPatternExecuted, const std::string&);
/**
* @brief Denotes when pattern editor has changed
*
* FIXME: this event is unused and should be scrapped.
*/
EVENT_DEF(EventPatternEditorChanged, const std::string&);
/**
* @brief Signals that a Content Store item was downloaded
*
* FIXME: this event is unused and should be scrapped.
*
* @param path the item's path on the filesystem
*/
EVENT_DEF(EventStoreContentDownloaded, const std::fs::path&);
/**
* @brief Signals the removal of a Content Store item
*
* Note: at the time of the event firing, the item has already been removed from the filesystem.
*
* FIXME: this event is unused and should be scrapped.
*
* @param path the item's old file path where it used to be in the filesystem
*/
EVENT_DEF(EventStoreContentRemoved, const std::fs::path&);
/**
* @brief Signals the unlocking of an achievement
*
* This is used by the achievement manager to refresh the achievement display, as well as store progress to
* the appropriate storage file.
*
* @param achievement the achievement that was unlocked
*/
EVENT_DEF(EventAchievementUnlocked, const Achievement&);
/**
* @brief Signals a click on the search box
*
* As there are different behaviours depending on the click (left or right) done by the user,
* this allows the consequences of said click to be registered in their own components.
*
* @param button the ImGuiMouseButton's value
*/
EVENT_DEF(EventSearchBoxClicked, u32);
/**
* @brief Updates on whether a file is being dragged into ImHex
*
* Allows ImGUi to display a file dragging information on screen when a file is being dragged.
*
* @param isFileDragged true if a file is being dragged
*/
EVENT_DEF(EventFileDragged, bool);
/**
* @brief Triggers loading when a file is dropped
*
* The event fires when a file is dropped into ImHex, which passes it to file handlers to load it.
*
* @param path the dropped file's path
*/
EVENT_DEF(EventFileDropped, std::fs::path);
}

View File

@@ -1,78 +0,0 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* Lifecycle events definitions */
namespace hex {
/**
* @brief Called when Imhex finished startup, and will enter the main window rendering loop
*/
EVENT_DEF(EventImHexStartupFinished);
/**
* @brief Called when ImHex is closing, to trigger the last shutdown hooks
*
* This is the last event to fire before complete graceful shutdown.
*/
EVENT_DEF(EventImHexClosing);
/**
* @brief Signals that it's ImHex first launch ever
*
* This event allows for the launch of the ImHex tutorial (also called Out of Box experience).
*/
EVENT_DEF(EventFirstLaunch);
/**
* FIXME: this event is unused and should be scrapped.
*/
EVENT_DEF(EventAnySettingChanged);
/**
* @brief Ensures correct plugin cleanup on crash
*
* This event is fired when catching an unexpected error that cannot be recovered and
* which forces Imhex to close immediately.
*
* Subscribing to this event ensures that the plugin can correctly clean up any mission-critical tasks
* before forceful shutdown.
*
* @param signal the POSIX signal code
*/
EVENT_DEF(EventAbnormalTermination, int);
/**
* @brief Informs of the ImHex versions (and difference, if any)
*
* Called on every startup to inform subscribers of the two versions picked up:
* - the version of the previous launch, gathered from the settings file
* - the current version, gathered directly from C++ code
*
* In most cases, and unless ImHex was updated, the two parameters will be the same.
*
* FIXME: Maybe rename the event to signal a startup information, instead of the misleading
* title that the event could be fired when ImHex detects that it was updated since last launch?
*
* @param previousLaunchVersion ImHex's version during the previous launch
* @param currentVersion ImHex's current version for this startup
*/
EVENT_DEF(EventImHexUpdated, SemanticVersion, SemanticVersion);
/**
* @brief Called when ImHex managed to catch an error in a general try/catch to prevent/recover from a crash
*/
EVENT_DEF(EventCrashRecovered, const std::exception &);
/**
* @brief Called when a project has been loaded
*/
EVENT_DEF(EventProjectOpened);
/**
* @brief Called when a native message was received from another ImHex instance
* @param rawData Raw bytes received from other instance
*/
EVENT_DEF(EventNativeMessageReceived, std::vector<u8>);
}

View File

@@ -1,113 +0,0 @@
#pragma once
#include <hex.hpp>
#include <hex/api/event_manager.hpp>
/* Provider events definitions */
namespace hex {
/**
* @brief Called when the provider is created.
* This event is responsible for (optionally) initializing the provider and calling EventProviderOpened
* (although the event can also be called manually without problem)
*/
EVENT_DEF(EventProviderCreated, prv::Provider *);
/**
* @brief Called as a continuation of EventProviderCreated
* this event is normally called immediately after EventProviderCreated successfully initialized the provider.
* If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually
* If skipLoadInterface failed, this event is not called
*
* @note this is not related to Provider::open()
*/
EVENT_DEF(EventProviderOpened, prv::Provider *);
/**
* @brief Signals a change in provider (in-place)
*
* Note: if the provider was deleted, the new ("current") provider will be `nullptr`
*
* @param oldProvider the old provider
* @param currentProvider the current provider
*/
EVENT_DEF(EventProviderChanged, prv::Provider *, prv::Provider *);
/**
* @brief Signals that a provider was saved
*
* @param provider the saved provider
*/
EVENT_DEF(EventProviderSaved, prv::Provider *);
/**
* @brief Signals a provider is closing
*
* FIXME: as for now, this behaves as a request more than an event. Also, the boolean is always set to true,
* and serves no purpose. This should be moved into the Provider requests section and declared accordingly.
*
* @param provider the closing provider
* @param shouldClose whether the provider should close
*/
EVENT_DEF(EventProviderClosing, prv::Provider *, bool *);
/**
* @brief Signals that a provider was closed
*
* As this is a closure information broadcast, the provider should generally not be accessed, as it could
* result in problems.
*
* @param provider the now-closed provider
*/
EVENT_DEF(EventProviderClosed, prv::Provider *);
/**
* @brief Signals that a provider is being deleted
*
* Provider's data should not be accessed.
*
* @param provider the provider
*/
EVENT_DEF(EventProviderDeleted, prv::Provider *);
}
/* Provider data events definitions */
namespace hex {
/**
* @brief Signals the dirtying of a provider
*
* Any data modification that occurs in a provider dirties it, until its state is either saved or restored.
* This event signals that fact to subscribers so additional code can be executed for certain cases.
*/
EVENT_DEF(EventProviderDirtied, prv::Provider *);
/**
* @brief Signals an insertion of new data into a provider
*
* @param provider the provider
* @param offset the start of the insertion
* @param size the new data's size
*/
EVENT_DEF(EventProviderDataInserted, prv::Provider *, u64, u64);
/**
* @brief Signals a modification in the provider's data
*
* @param provider the provider
* @param offset the data modification's offset (start address)
* @param size the buffer's size
* @param buffer the modified data written at this address
*/
EVENT_DEF(EventProviderDataModified, prv::Provider *, u64, u64, const u8*);
/**
* @brief Signals a removal of some of the provider's data
*
* @param provider the provider
* @param offset the deletion offset (start address)
* @param size the deleted data's size
*/
EVENT_DEF(EventProviderDataRemoved, prv::Provider *, u64, u64);
}

View File

@@ -1,37 +0,0 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* GUI requests definitions */
namespace hex {
/**
* @brief Requests the opening of a new window.
*
* @param name the window's name
*/
EVENT_DEF(RequestOpenWindow, std::string);
/**
* @brief Centralized request to update ImHex's main window title
*
* This request can be called to make ImHex refresh its main window title, taking into account a new project
* or file opened/closed.
*/
EVENT_DEF(RequestUpdateWindowTitle);
/**
* @brief Requests a theme type (light or dark) change
*
* @param themeType either `Light` or `Dark`
*/
EVENT_DEF(RequestChangeTheme, std::string);
/**
* @brief Requests the opening of a popup
*
* @param name the popup's name
*/
EVENT_DEF(RequestOpenPopup, std::string);
}

View File

@@ -1,116 +0,0 @@
#pragma once
#include <hex.hpp>
#include <hex/api/event_manager.hpp>
/* Forward declarations */
namespace pl::ptrn { class Pattern; }
/* Interaction requests definitions */
namespace hex {
/**
* @brief Requests a selection change in the Hex editor
*
* This request is handled by the Hex editor, which proceeds to check if the selection is valid.
* If it is invalid, the Hex editor fires the `EventRegionSelected` event with nullptr region info.
*
* @param region the region that should be selected
*/
EVENT_DEF(RequestHexEditorSelectionChange, ImHexApi::HexEditor::ProviderRegion);
/**
* @brief Requests the Pattern editor to move selection
*
* Requests the Pattern editor to move the cursor's position to reflect the user's click or movement.
*
* @param line the target line
* @param column the target column
*/
EVENT_DEF(RequestPatternEditorSelectionChange, u32, u32);
/**
* @brief Requests a jump to a given pattern
*
* This request is fired by the Hex editor when the user asks to jump to the pattern.
* It is then caught and reflected by the Pattern data component.
*
* @param pattern the pattern to jump to
*/
EVENT_DEF(RequestJumpToPattern, const pl::ptrn::Pattern*);
/**
* @brief Requests to add a bookmark
*
* @param region the region to be bookmarked
* @param name the bookmark's name
* @param comment a comment
* @param color the color
* @param id the bookmark's unique ID
*/
EVENT_DEF(RequestAddBookmark, Region, std::string, std::string, color_t, u64*);
/**
* @brief Requests a bookmark removal
*
* @param id the bookmark's unique ID
*/
EVENT_DEF(RequestRemoveBookmark, u64);
/**
* @brief Request the Pattern editor to set its code
*
* This request allows the rest of ImHex to interface with the Pattern editor component, by setting its code.
* This allows for `.hexpat` file loading, and more.
*
* @param code the code's string
*/
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
/**
* @brief Requests the Pattern editor to run the current code
*
* This is only ever used in the introduction tutorial.
*
* FIXME: the name is misleading, as for now this activates the pattern's auto-evaluation rather than a
* one-off execution
*/
EVENT_DEF(RequestRunPatternCode);
/**
* @brief Request to load a pattern language file
*
* FIXME: this request is unused, as now another component is responsible for pattern file loading.
* This request should be scrapped.
*
* @param path the pattern file's path
*/
EVENT_DEF(RequestLoadPatternLanguageFile, std::fs::path);
/**
* @brief Request to save a pattern language file
*
* FIXME: this request is unused, as now another component is responsible for pattern file saving.
* This request should be scrapped.
*
* @param path the pattern file's path
*/
EVENT_DEF(RequestSavePatternLanguageFile, std::fs::path);
/**
* @brief Requests ImHex to open and process a file
*
* @param path the file's path
*/
EVENT_DEF(RequestOpenFile, std::fs::path);
/**
* @brief Adds a virtual file in the Pattern editor
*
* @param path the file's path
* @param data the file's data
* @param region the impacted region
*/
EVENT_DEF(RequestAddVirtualFile, std::fs::path, std::vector<u8>, Region);
}

View File

@@ -1,84 +0,0 @@
#pragma once
#include <hex.hpp>
#include <hex/api/event_manager.hpp>
/* Lifecycle requests definitions */
namespace hex {
/**
* @brief Emit a request to add an initialization task to the list
*
* These tasks will be executed at startup.
*
* @param name Name of the init task
* @param isAsync Whether the task is asynchronous (true if yes)
* @param callbackFunction The function to call to execute the task
*/
EVENT_DEF(RequestAddInitTask, std::string, bool, std::function<bool()>);
/**
* @brief Emit a request to add an exit task to the list
*
* These tasks will be executed during the exit phase.
*
* FIXME: request is unused and should be scrapped.
*
* @param name Name of the exit task
* @param callbackFunction The function to call to execute the task
*/
EVENT_DEF(RequestAddExitTask, std::string, std::function<bool()>);
/**
* @brief Requests ImHex's graceful shutdown
*
* If there are no questions (bool set to true), ImHex closes immediately.
* If set to false, there is a procedure run to prompt a confirmation to the user.
*
* @param noQuestions true if no questions
*/
EVENT_DEF(RequestCloseImHex, bool);
/**
* @brief Requests ImHex's restart
*
* This event is necessary for ImHex to restart in the main loop for native and web platforms,
* as ImHex cannot simply close and re-open.
*
* This event serves no purpose on Linux, Windows and macOS platforms.
*/
EVENT_DEF(RequestRestartImHex);
/**
* @brief Requests the initialization of theme handlers
*
* This is called during ImGui bootstrapping, and should not be called at any other time.
*/
EVENT_DEF(RequestInitThemeHandlers);
/**
* @brief Requests version and first-startup checks
*
* This request is called during ImHex's startup, and allows ImHex to check if it was updated since last launch.
* It also ensures newcomers (that open ImHex for the first time) are greeted with the tutorial.
*
* FIXME: the name is misleading, as this request does not effectively start any migration. It only executes
* checks about ImHex's version. The name should be changed to reflect this behaviour.
*/
EVENT_DEF(RequestStartMigration);
/**
* @brief Send a subcommand to the main Imhex instance
*
* This request is called to send a subcommand to the main ImHex instance.
* This subcommand will then be executed by a handler when ImHex finishing initializing
* (`EventImHexStartupFinished`).
*
* FIXME: change the name so that it is prefixed with "Request" like every other request.
*
* @param name the subcommand's name
* @param data the subcommand's data
*/
EVENT_DEF(SendMessageToMainInstance, const std::string, const std::vector<u8>&);
}

View File

@@ -1,22 +0,0 @@
#pragma once
#include <hex/api/event_manager.hpp>
/* Provider requests definitions */
namespace hex {
/**
* @brief Creates a provider from its unlocalized name, and add it to the provider list
*/
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, hex::prv::Provider **);
/**
* @brief 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
*
* FIXME: rename with the "Request" prefix to apply standard naming convention.
*/
EVENT_DEF(MovePerProviderData, prv::Provider *, prv::Provider *);
}

View File

@@ -2,8 +2,6 @@
#include <hex.hpp> #include <hex.hpp>
#include <hex/api/localization_manager.hpp> #include <hex/api/localization_manager.hpp>
#include <hex/helpers/semantic_version.hpp>
#include <hex/helpers/fs.hpp>
#include <functional> #include <functional>
#include <optional> #include <optional>
@@ -12,7 +10,8 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <set> #include <set>
#include <memory>
#include <wolv/io/fs.hpp>
using ImGuiID = unsigned int; using ImGuiID = unsigned int;
struct ImVec2; struct ImVec2;
@@ -76,7 +75,7 @@ namespace hex {
namespace impl { namespace impl {
using HighlightingFunction = std::function<std::optional<color_t>(u64, const u8*, size_t, bool)>; using HighlightingFunction = std::function<std::optional<color_t>(u64, const u8*, size_t, bool)>;
using HoveringFunction = std::function<std::set<Region>(const prv::Provider *, u64, size_t)>; using HoveringFunction = std::function<bool(const prv::Provider *, u64, const u8*, size_t)>;
const std::map<u32, Highlighting>& getBackgroundHighlights(); const std::map<u32, Highlighting>& getBackgroundHighlights();
const std::map<u32, HighlightingFunction>& getBackgroundHighlightingFunctions(); const std::map<u32, HighlightingFunction>& getBackgroundHighlightingFunctions();
@@ -294,7 +293,7 @@ namespace hex {
namespace impl { namespace impl {
void resetClosingProvider(); void resetClosingProvider();
std::set<prv::Provider*> getClosingProviders(); const std::set<prv::Provider*>& getClosingProviders();
} }
@@ -435,7 +434,6 @@ namespace hex {
void setInitialWindowProperties(InitialWindowProperties properties); void setInitialWindowProperties(InitialWindowProperties properties);
void setGPUVendor(const std::string &vendor); void setGPUVendor(const std::string &vendor);
void setGLRenderer(const std::string &renderer);
void addInitArgument(const std::string &key, const std::string &value = { }); void addInitArgument(const std::string &key, const std::string &value = { });
@@ -444,8 +442,6 @@ namespace hex {
bool isWindowResizable(); bool isWindowResizable();
void addAutoResetObject(hex::impl::AutoResetBase *object); void addAutoResetObject(hex::impl::AutoResetBase *object);
void removeAutoResetObject(hex::impl::AutoResetBase *object);
void cleanup(); void cleanup();
} }
@@ -495,7 +491,6 @@ namespace hex {
*/ */
float getNativeScale(); float getNativeScale();
float getBackingScaleFactor();
/** /**
* @brief Gets the current main window position * @brief Gets the current main window position
@@ -578,20 +573,6 @@ namespace hex {
*/ */
const std::string& getGPUVendor(); const std::string& getGPUVendor();
/**
* @brief Gets the current GPU vendor
* @return The current GPU vendor
*/
const std::string& getGLRenderer();
/**
* @brief Checks if ImHex is being run in a "Corporate Environment"
* This function simply checks for common telltale signs such as if the machine is joined a
* domain. It's not super accurate, but it's still useful for statistics
* @return True if it is
*/
bool isCorporateEnvironment();
/** /**
* @brief Checks if ImHex is running in portable mode * @brief Checks if ImHex is running in portable mode
* @return Whether ImHex is running in portable mode * @return Whether ImHex is running in portable mode
@@ -616,21 +597,11 @@ namespace hex {
*/ */
std::string getArchitecture(); std::string getArchitecture();
struct LinuxDistro {
std::string name;
std::string version;
};
/**
* @brief Gets information related to the Linux distribution, if running on Linux
*/
std::optional<LinuxDistro> getLinuxDistro();
/** /**
* @brief Gets the current ImHex version * @brief Gets the current ImHex version
* @return ImHex version * @return ImHex version
*/ */
SemanticVersion getImHexVersion(); std::string getImHexVersion(bool withBuildType = true);
/** /**
* @brief Gets the current git commit hash * @brief Gets the current git commit hash
@@ -651,12 +622,6 @@ namespace hex {
*/ */
bool isDebugBuild(); bool isDebugBuild();
/**
* @brief Checks if this version of ImHex is a nightly build
* @return True if this version is a nightly, false if it's a release
*/
bool isNightlyBuild();
enum class UpdateType { enum class UpdateType {
Stable, Stable,
Nightly Nightly
@@ -707,13 +672,6 @@ namespace hex {
*/ */
void* getLibImHexModuleHandle(); void* getLibImHexModuleHandle();
/**
* Adds a new migration routine that will be executed when upgrading from a lower version than specified in migrationVersion
* @param migrationVersion Upgrade point version
* @param function Function to run
*/
void addMigrationRoutine(SemanticVersion migrationVersion, std::function<void()> function);
} }
/** /**
@@ -755,8 +713,11 @@ namespace hex {
const std::vector<Font>& getFonts(); const std::vector<Font>& getFonts();
std::map<UnlocalizedString, ImFont*>& getFontDefinitions(); void setCustomFontPath(const std::fs::path &path);
void setFontSize(float size);
void setFontAtlas(ImFontAtlas *fontAtlas);
void setFonts(ImFont *bold, ImFont *italic);
} }
GlyphRange glyph(const char *glyph); GlyphRange glyph(const char *glyph);
@@ -769,8 +730,26 @@ namespace hex {
constexpr static float DefaultFontSize = 13.0; constexpr static float DefaultFontSize = 13.0;
void registerFont(const UnlocalizedString &fontName); ImFont* Bold();
ImFont* getFont(const UnlocalizedString &fontName); ImFont* Italic();
/**
* @brief Gets the current custom font path
* @return The current custom font path
*/
const std::filesystem::path& getCustomFontPath();
/**
* @brief Gets the current font size
* @return The current font size
*/
float getFontSize();
/**
* @brief Gets the current font atlas
* @return Current font atlas
*/
ImFontAtlas* getFontAtlas();
} }

View File

@@ -1,14 +1,11 @@
#pragma once #pragma once
#include <hex.hpp>
#include <map> #include <map>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <fmt/core.h> #include <fmt/format.h>
#include <wolv/types/static_string.hpp>
namespace hex { namespace hex {
@@ -25,30 +22,24 @@ namespace hex {
}; };
namespace impl { namespace impl {
void setFallbackLanguage(const std::string &language); void setFallbackLanguage(const std::string &language);
void resetLanguageStrings(); void resetLanguageStrings();
} }
void loadLanguage(std::string language); void loadLanguage(const std::string &language);
std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = ""); std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = "");
[[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages(); [[nodiscard]] const std::map<std::string, std::string> &getSupportedLanguages();
[[nodiscard]] const std::string &getFallbackLanguage(); [[nodiscard]] const std::string &getFallbackLanguage();
[[nodiscard]] const std::string &getSelectedLanguage(); [[nodiscard]] const std::string &getSelectedLanguage();
} }
struct UnlocalizedString; struct UnlocalizedString;
class LangConst;
class Lang { class Lang {
public: public:
explicit Lang(const char *unlocalizedString); explicit Lang(const char *unlocalizedString);
explicit Lang(const std::string &unlocalizedString); explicit Lang(const std::string &unlocalizedString);
explicit(false) Lang(const LangConst &localizedString);
explicit Lang(const UnlocalizedString &unlocalizedString); explicit Lang(const UnlocalizedString &unlocalizedString);
explicit Lang(std::string_view unlocalizedString); explicit Lang(std::string_view unlocalizedString);
@@ -56,54 +47,31 @@ namespace hex {
[[nodiscard]] operator std::string_view() const; [[nodiscard]] operator std::string_view() const;
[[nodiscard]] operator const char *() const; [[nodiscard]] operator const char *() const;
const char* get() const; [[nodiscard]] const std::string &get() const;
private: private:
std::size_t m_entryHash;
std::string m_unlocalizedString; std::string m_unlocalizedString;
}; };
class LangConst { [[nodiscard]] std::string operator+(const std::string &&left, const Lang &&right);
public: [[nodiscard]] std::string operator+(const Lang &&left, const std::string &&right);
[[nodiscard]] operator std::string() const; [[nodiscard]] std::string operator+(const std::string_view &&left, const Lang &&right);
[[nodiscard]] operator std::string_view() const; [[nodiscard]] std::string operator+(const Lang &&left, const std::string_view &&right);
[[nodiscard]] operator const char *() const; [[nodiscard]] std::string operator+(const char *left, const Lang &&right);
[[nodiscard]] std::string operator+(const Lang &&left, const char *right);
[[nodiscard]] std::string operator+(const Lang &&left, const Lang &&right);
const char* get() const; [[nodiscard]] inline Lang operator""_lang(const char *string, size_t) {
return Lang(string);
}
constexpr static size_t hash(std::string_view string) {
constexpr u64 p = 131;
constexpr u64 m = std::numeric_limits<std::uint32_t>::max() - 4;
u64 total = 0;
u64 currentMultiplier = 1;
for (char c : string) {
total = (total + currentMultiplier * c) % m;
currentMultiplier = (currentMultiplier * p) % m;
}
return total;
}
private:
constexpr explicit LangConst(std::size_t hash, const char *unlocalizedString) : m_entryHash(hash), m_unlocalizedString(unlocalizedString) {}
template<wolv::type::StaticString>
friend consteval LangConst operator""_lang();
friend class Lang;
private:
std::size_t m_entryHash;
const char *m_unlocalizedString = nullptr;
};
struct UnlocalizedString { struct UnlocalizedString {
public: public:
UnlocalizedString() = default; UnlocalizedString() = default;
UnlocalizedString(auto && arg) : m_unlocalizedString(std::forward<decltype(arg)>(arg)) {
UnlocalizedString(const std::string &string) : m_unlocalizedString(string) { } static_assert(!std::same_as<std::remove_cvref_t<decltype(arg)>, Lang>, "Expected a unlocalized name, got a localized one!");
UnlocalizedString(const char *string) : m_unlocalizedString(string) { } }
UnlocalizedString(const Lang& arg) = delete;
[[nodiscard]] operator std::string() const { [[nodiscard]] operator std::string() const {
return m_unlocalizedString; return m_unlocalizedString;
@@ -134,24 +102,12 @@ namespace hex {
std::string m_unlocalizedString; std::string m_unlocalizedString;
}; };
template<wolv::type::StaticString String>
[[nodiscard]] consteval LangConst operator""_lang() {
return LangConst(LangConst::hash(String.value.data()), String.value.data());
}
// {fmt} formatter for hex::Lang and hex::LangConst
inline auto format_as(const hex::Lang &entry) {
return entry.get();
}
inline auto format_as(const hex::LangConst &entry) {
return entry.get();
}
} }
template<> template<>
struct std::hash<hex::UnlocalizedString> { struct fmt::formatter<hex::Lang> : fmt::formatter<std::string_view> {
std::size_t operator()(const hex::UnlocalizedString &string) const noexcept { template<typename FormatContext>
return std::hash<std::string>{}(string.get()); auto format(const hex::Lang &entry, FormatContext &ctx) {
return fmt::formatter<std::string_view>::format(entry.get(), ctx);
} }
}; };

View File

@@ -15,17 +15,11 @@ struct ImGuiContext;
namespace hex { namespace hex {
struct SubCommand { struct SubCommand {
enum class Type : u8 {
Option,
SubCommand
};
std::string commandLong; std::string commandLong;
std::string commandShort; std::string commandShort;
std::string commandDescription; std::string commandDescription;
std::function<void(const std::vector<std::string>&)> callback; std::function<void(const std::vector<std::string>&)> callback;
Type type = Type::Option;
}; };
struct Feature { struct Feature {

View File

@@ -2,31 +2,142 @@
#include <hex.hpp> #include <hex.hpp>
#include <hex/api/localization_manager.hpp> #include <hex/api/localization_manager.hpp>
#include <hex/helpers/keys.hpp>
#include <functional> #include <functional>
#include <memory>
#include <optional> #include <optional>
#include <set> #include <set>
#include <string> #include <string>
struct ImGuiWindow; #include <GLFW/glfw3.h>
struct KeyEquivalent { struct ImGuiWindow;
bool valid;
bool ctrl, opt, cmd, shift;
int key;
};
namespace hex { namespace hex {
class View; class View;
enum class Keys {
Space = GLFW_KEY_SPACE,
Apostrophe = GLFW_KEY_APOSTROPHE,
Comma = GLFW_KEY_COMMA,
Minus = GLFW_KEY_MINUS,
Period = GLFW_KEY_PERIOD,
Slash = GLFW_KEY_SLASH,
Num0 = GLFW_KEY_0,
Num1 = GLFW_KEY_1,
Num2 = GLFW_KEY_2,
Num3 = GLFW_KEY_3,
Num4 = GLFW_KEY_4,
Num5 = GLFW_KEY_5,
Num6 = GLFW_KEY_6,
Num7 = GLFW_KEY_7,
Num8 = GLFW_KEY_8,
Num9 = GLFW_KEY_9,
Semicolon = GLFW_KEY_SEMICOLON,
Equals = GLFW_KEY_EQUAL,
A = GLFW_KEY_A,
B = GLFW_KEY_B,
C = GLFW_KEY_C,
D = GLFW_KEY_D,
E = GLFW_KEY_E,
F = GLFW_KEY_F,
G = GLFW_KEY_G,
H = GLFW_KEY_H,
I = GLFW_KEY_I,
J = GLFW_KEY_J,
K = GLFW_KEY_K,
L = GLFW_KEY_L,
M = GLFW_KEY_M,
N = GLFW_KEY_N,
O = GLFW_KEY_O,
P = GLFW_KEY_P,
Q = GLFW_KEY_Q,
R = GLFW_KEY_R,
S = GLFW_KEY_S,
T = GLFW_KEY_T,
U = GLFW_KEY_U,
V = GLFW_KEY_V,
W = GLFW_KEY_W,
X = GLFW_KEY_X,
Y = GLFW_KEY_Y,
Z = GLFW_KEY_Z,
LeftBracket = GLFW_KEY_LEFT_BRACKET,
Backslash = GLFW_KEY_BACKSLASH,
RightBracket = GLFW_KEY_RIGHT_BRACKET,
GraveAccent = GLFW_KEY_GRAVE_ACCENT,
World1 = GLFW_KEY_WORLD_1,
World2 = GLFW_KEY_WORLD_2,
Escape = GLFW_KEY_ESCAPE,
Enter = GLFW_KEY_ENTER,
Tab = GLFW_KEY_TAB,
Backspace = GLFW_KEY_BACKSPACE,
Insert = GLFW_KEY_INSERT,
Delete = GLFW_KEY_DELETE,
Right = GLFW_KEY_RIGHT,
Left = GLFW_KEY_LEFT,
Down = GLFW_KEY_DOWN,
Up = GLFW_KEY_UP,
PageUp = GLFW_KEY_PAGE_UP,
PageDown = GLFW_KEY_PAGE_DOWN,
Home = GLFW_KEY_HOME,
End = GLFW_KEY_END,
CapsLock = GLFW_KEY_CAPS_LOCK,
ScrollLock = GLFW_KEY_SCROLL_LOCK,
NumLock = GLFW_KEY_NUM_LOCK,
PrintScreen = GLFW_KEY_PRINT_SCREEN,
Pause = GLFW_KEY_PAUSE,
F1 = GLFW_KEY_F1,
F2 = GLFW_KEY_F2,
F3 = GLFW_KEY_F3,
F4 = GLFW_KEY_F4,
F5 = GLFW_KEY_F5,
F6 = GLFW_KEY_F6,
F7 = GLFW_KEY_F7,
F8 = GLFW_KEY_F8,
F9 = GLFW_KEY_F9,
F10 = GLFW_KEY_F10,
F11 = GLFW_KEY_F11,
F12 = GLFW_KEY_F12,
F13 = GLFW_KEY_F13,
F14 = GLFW_KEY_F14,
F15 = GLFW_KEY_F15,
F16 = GLFW_KEY_F16,
F17 = GLFW_KEY_F17,
F18 = GLFW_KEY_F18,
F19 = GLFW_KEY_F19,
F20 = GLFW_KEY_F20,
F21 = GLFW_KEY_F21,
F22 = GLFW_KEY_F22,
F23 = GLFW_KEY_F23,
F24 = GLFW_KEY_F24,
F25 = GLFW_KEY_F25,
KeyPad0 = GLFW_KEY_KP_0,
KeyPad1 = GLFW_KEY_KP_1,
KeyPad2 = GLFW_KEY_KP_2,
KeyPad3 = GLFW_KEY_KP_3,
KeyPad4 = GLFW_KEY_KP_4,
KeyPad5 = GLFW_KEY_KP_5,
KeyPad6 = GLFW_KEY_KP_6,
KeyPad7 = GLFW_KEY_KP_7,
KeyPad8 = GLFW_KEY_KP_8,
KeyPad9 = GLFW_KEY_KP_9,
KeyPadDecimal = GLFW_KEY_KP_DECIMAL,
KeyPadDivide = GLFW_KEY_KP_DIVIDE,
KeyPadMultiply = GLFW_KEY_KP_MULTIPLY,
KeyPadSubtract = GLFW_KEY_KP_SUBTRACT,
KeyPadAdd = GLFW_KEY_KP_ADD,
KeyPadEnter = GLFW_KEY_KP_ENTER,
KeyPadEqual = GLFW_KEY_KP_EQUAL,
Menu = GLFW_KEY_MENU,
};
class Key { class Key {
public: public:
constexpr Key() = default; constexpr Key() = default;
constexpr Key(Keys key) : m_key(static_cast<u32>(key)) { } constexpr Key(Keys key) : m_key(static_cast<u32>(key)) { }
bool operator==(const Key &) const = default;
auto operator<=>(const Key &) const = default; auto operator<=>(const Key &) const = default;
[[nodiscard]] constexpr u32 getKeyCode() const { return m_key; } [[nodiscard]] constexpr u32 getKeyCode() const { return m_key; }
@@ -41,32 +152,224 @@ namespace hex {
constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000)); constexpr static auto SUPER = Key(static_cast<Keys>(0x0800'0000));
constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000)); constexpr static auto CurrentView = Key(static_cast<Keys>(0x1000'0000));
constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000)); constexpr static auto AllowWhileTyping = Key(static_cast<Keys>(0x2000'0000));
constexpr static auto CTRLCMD = Key(static_cast<Keys>(0x4000'0000));
#if defined (OS_MACOS)
constexpr static auto CTRLCMD = SUPER;
#else
constexpr static auto CTRLCMD = CTRL;
#endif
class Shortcut { class Shortcut {
public: public:
Shortcut() = default; Shortcut() = default;
Shortcut(Keys key); Shortcut(Keys key) : m_keys({ key }) { }
explicit Shortcut(std::set<Key> keys); explicit Shortcut(std::set<Key> keys) : m_keys(std::move(keys)) { }
Shortcut(const Shortcut &other) = default; Shortcut(const Shortcut &other) = default;
Shortcut(Shortcut &&) noexcept = default; Shortcut(Shortcut &&) noexcept = default;
constexpr static auto None = Keys(0);
Shortcut& operator=(const Shortcut &other) = default; Shortcut& operator=(const Shortcut &other) = default;
Shortcut& operator=(Shortcut &&) noexcept = default; Shortcut& operator=(Shortcut &&) noexcept = default;
Shortcut operator+(const Key &other) const; constexpr static inline auto None = Keys(0);
Shortcut &operator+=(const Key &other);
bool operator<(const Shortcut &other) const;
bool operator==(const Shortcut &other) const;
bool isLocal() const; Shortcut operator+(const Key &other) const {
std::string toString() const; Shortcut result = *this;
KeyEquivalent toKeyEquivalent() const; result.m_keys.insert(other);
const std::set<Key>& getKeys() const;
bool has(Key key) const; return result;
bool matches(const Shortcut &other) const; }
Shortcut &operator+=(const Key &other) {
m_keys.insert(other);
return *this;
}
bool operator<(const Shortcut &other) const {
return m_keys < other.m_keys;
}
bool operator==(const Shortcut &other) const {
auto thisKeys = m_keys;
auto otherKeys = other.m_keys;
thisKeys.erase(CurrentView);
thisKeys.erase(AllowWhileTyping);
otherKeys.erase(CurrentView);
otherKeys.erase(AllowWhileTyping);
return thisKeys == otherKeys;
}
bool isLocal() const {
return m_keys.contains(CurrentView);
}
std::string toString() const {
std::string result;
#if defined(OS_MACOS)
constexpr static auto CTRL_NAME = "CTRL";
constexpr static auto ALT_NAME = "OPT";
constexpr static auto SHIFT_NAME = "SHIFT";
constexpr static auto SUPER_NAME = "CMD";
#else
constexpr static auto CTRL_NAME = "CTRL";
constexpr static auto ALT_NAME = "ALT";
constexpr static auto SHIFT_NAME = "SHIFT";
constexpr static auto SUPER_NAME = "SUPER";
#endif
constexpr static auto Concatination = " + ";
auto keys = m_keys;
if (keys.erase(CTRL) > 0) {
result += CTRL_NAME;
result += Concatination;
}
if (keys.erase(ALT) > 0) {
result += ALT_NAME;
result += Concatination;
}
if (keys.erase(SHIFT) > 0) {
result += SHIFT_NAME;
result += Concatination;
}
if (keys.erase(SUPER) > 0) {
result += SUPER_NAME;
result += Concatination;
}
keys.erase(CurrentView);
for (const auto &key : keys) {
switch (Keys(key.getKeyCode())) {
case Keys::Space: result += "SPACE"; break;
case Keys::Apostrophe: result += "'"; break;
case Keys::Comma: result += ","; break;
case Keys::Minus: result += "-"; break;
case Keys::Period: result += "."; break;
case Keys::Slash: result += "/"; break;
case Keys::Num0: result += "0"; break;
case Keys::Num1: result += "1"; break;
case Keys::Num2: result += "2"; break;
case Keys::Num3: result += "3"; break;
case Keys::Num4: result += "4"; break;
case Keys::Num5: result += "5"; break;
case Keys::Num6: result += "6"; break;
case Keys::Num7: result += "7"; break;
case Keys::Num8: result += "8"; break;
case Keys::Num9: result += "9"; break;
case Keys::Semicolon: result += ";"; break;
case Keys::Equals: result += "="; break;
case Keys::A: result += "A"; break;
case Keys::B: result += "B"; break;
case Keys::C: result += "C"; break;
case Keys::D: result += "D"; break;
case Keys::E: result += "E"; break;
case Keys::F: result += "F"; break;
case Keys::G: result += "G"; break;
case Keys::H: result += "H"; break;
case Keys::I: result += "I"; break;
case Keys::J: result += "J"; break;
case Keys::K: result += "K"; break;
case Keys::L: result += "L"; break;
case Keys::M: result += "M"; break;
case Keys::N: result += "N"; break;
case Keys::O: result += "O"; break;
case Keys::P: result += "P"; break;
case Keys::Q: result += "Q"; break;
case Keys::R: result += "R"; break;
case Keys::S: result += "S"; break;
case Keys::T: result += "T"; break;
case Keys::U: result += "U"; break;
case Keys::V: result += "V"; break;
case Keys::W: result += "W"; break;
case Keys::X: result += "X"; break;
case Keys::Y: result += "Y"; break;
case Keys::Z: result += "Z"; break;
case Keys::LeftBracket: result += "["; break;
case Keys::Backslash: result += "\\"; break;
case Keys::RightBracket: result += "]"; break;
case Keys::GraveAccent: result += "`"; break;
case Keys::World1: result += "WORLD1"; break;
case Keys::World2: result += "WORLD2"; break;
case Keys::Escape: result += "ESC"; break;
case Keys::Enter: result += "ENTER"; break;
case Keys::Tab: result += "TAB"; break;
case Keys::Backspace: result += "BACKSPACE"; break;
case Keys::Insert: result += "INSERT"; break;
case Keys::Delete: result += "DELETE"; break;
case Keys::Right: result += "RIGHT"; break;
case Keys::Left: result += "LEFT"; break;
case Keys::Down: result += "DOWN"; break;
case Keys::Up: result += "UP"; break;
case Keys::PageUp: result += "PAGEUP"; break;
case Keys::PageDown: result += "PAGEDOWN"; break;
case Keys::Home: result += "HOME"; break;
case Keys::End: result += "END"; break;
case Keys::CapsLock: result += "CAPSLOCK"; break;
case Keys::ScrollLock: result += "SCROLLLOCK"; break;
case Keys::NumLock: result += "NUMLOCK"; break;
case Keys::PrintScreen: result += "PRINTSCREEN"; break;
case Keys::Pause: result += "PAUSE"; break;
case Keys::F1: result += "F1"; break;
case Keys::F2: result += "F2"; break;
case Keys::F3: result += "F3"; break;
case Keys::F4: result += "F4"; break;
case Keys::F5: result += "F5"; break;
case Keys::F6: result += "F6"; break;
case Keys::F7: result += "F7"; break;
case Keys::F8: result += "F8"; break;
case Keys::F9: result += "F9"; break;
case Keys::F10: result += "F10"; break;
case Keys::F11: result += "F11"; break;
case Keys::F12: result += "F12"; break;
case Keys::F13: result += "F13"; break;
case Keys::F14: result += "F14"; break;
case Keys::F15: result += "F15"; break;
case Keys::F16: result += "F16"; break;
case Keys::F17: result += "F17"; break;
case Keys::F18: result += "F18"; break;
case Keys::F19: result += "F19"; break;
case Keys::F20: result += "F20"; break;
case Keys::F21: result += "F21"; break;
case Keys::F22: result += "F22"; break;
case Keys::F23: result += "F23"; break;
case Keys::F24: result += "F24"; break;
case Keys::F25: result += "F25"; break;
case Keys::KeyPad0: result += "KP0"; break;
case Keys::KeyPad1: result += "KP1"; break;
case Keys::KeyPad2: result += "KP2"; break;
case Keys::KeyPad3: result += "KP3"; break;
case Keys::KeyPad4: result += "KP4"; break;
case Keys::KeyPad5: result += "KP5"; break;
case Keys::KeyPad6: result += "KP6"; break;
case Keys::KeyPad7: result += "KP7"; break;
case Keys::KeyPad8: result += "KP8"; break;
case Keys::KeyPad9: result += "KP9"; break;
case Keys::KeyPadDecimal: result += "KPDECIMAL"; break;
case Keys::KeyPadDivide: result += "KPDIVIDE"; break;
case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break;
case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break;
case Keys::KeyPadAdd: result += "KPADD"; break;
case Keys::KeyPadEnter: result += "KPENTER"; break;
case Keys::KeyPadEqual: result += "KPEQUAL"; break;
case Keys::Menu: result += "MENU"; break;
default:
continue;
}
result += " + ";
}
if (result.ends_with(" + "))
result = result.substr(0, result.size() - 3);
return result;
}
const std::set<Key>& getKeys() const { return m_keys; }
private: private:
friend Shortcut operator+(const Key &lhs, const Key &rhs); friend Shortcut operator+(const Key &lhs, const Key &rhs);
@@ -74,7 +377,12 @@ namespace hex {
std::set<Key> m_keys; std::set<Key> m_keys;
}; };
Shortcut operator+(const Key &lhs, const Key &rhs); inline Shortcut operator+(const Key &lhs, const Key &rhs) {
Shortcut result;
result.m_keys = { lhs, rhs };
return result;
}
/** /**
* @brief The ShortcutManager handles global and view-specific shortcuts. * @brief The ShortcutManager handles global and view-specific shortcuts.
@@ -83,12 +391,10 @@ namespace hex {
class ShortcutManager { class ShortcutManager {
public: public:
using Callback = std::function<void()>; using Callback = std::function<void()>;
using EnabledCallback = std::function<bool()>;
struct ShortcutEntry { struct ShortcutEntry {
Shortcut shortcut; Shortcut shortcut;
std::vector<UnlocalizedString> unlocalizedName; UnlocalizedString unlocalizedName;
Callback callback; Callback callback;
EnabledCallback enabledCallback;
}; };
/** /**
@@ -96,10 +402,8 @@ namespace hex {
* @param shortcut The shortcut to add. * @param shortcut The shortcut to add.
* @param unlocalizedName The unlocalized name of the shortcut * @param unlocalizedName The unlocalized name of the shortcut
* @param callback The callback to call when the shortcut is triggered. * @param callback The callback to call when the shortcut is triggered.
* @param enabledCallback Callback that's called to check if this shortcut is enabled
*/ */
static void addGlobalShortcut(const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; }); static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
static void addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
/** /**
* @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused. * @brief Add a view-specific shortcut. View-specific shortcuts can only be triggered when the specified view is focused.
@@ -107,10 +411,8 @@ namespace hex {
* @param shortcut The shortcut to add. * @param shortcut The shortcut to add.
* @param unlocalizedName The unlocalized name of the shortcut * @param unlocalizedName The unlocalized name of the shortcut
* @param callback The callback to call when the shortcut is triggered. * @param callback The callback to call when the shortcut is triggered.
* @param enabledCallback Callback that's called to check if this shortcut is enabled
*/ */
static void addShortcut(View *view, const Shortcut &shortcut, const std::vector<UnlocalizedString> &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; }); static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback);
static void addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const Callback &callback, const EnabledCallback &enabledCallback = []{ return true; });
/** /**
@@ -135,14 +437,6 @@ namespace hex {
*/ */
static void processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode); static void processGlobals(bool ctrl, bool alt, bool shift, bool super, u32 keyCode);
/**
* @brief Runs the callback of a shortcut as if it was pressed on the keyboard
* @param shortcut Shortcut to run
* @param view View the shortcut belongs to or nullptr to run a global shortcut
* @return True if a callback was executed, false if not
*/
static bool runShortcut(const Shortcut &shortcut, const View *view = nullptr);
/** /**
* @brief Clear all shortcuts * @brief Clear all shortcuts
*/ */
@@ -151,17 +445,12 @@ namespace hex {
static void resumeShortcuts(); static void resumeShortcuts();
static void pauseShortcuts(); static void pauseShortcuts();
static void enableMacOSMode();
[[nodiscard]] static std::optional<UnlocalizedString> getLastActivatedMenu();
static void resetLastActivatedMenu();
[[nodiscard]] static std::optional<Shortcut> getPreviousShortcut(); [[nodiscard]] static std::optional<Shortcut> getPreviousShortcut();
[[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts(); [[nodiscard]] static std::vector<ShortcutEntry> getGlobalShortcuts();
[[nodiscard]] static std::vector<ShortcutEntry> getViewShortcuts(const View *view); [[nodiscard]] static std::vector<ShortcutEntry> getViewShortcuts(const View *view);
[[nodiscard]] static bool updateShortcut(const Shortcut &oldShortcut, Shortcut newShortcut, View *view = nullptr); [[nodiscard]] static bool updateShortcut(const Shortcut &oldShortcut, const Shortcut &newShortcut, View *view = nullptr);
}; };
} }

View File

@@ -22,7 +22,7 @@ namespace hex {
class Task { class Task {
public: public:
Task() = default; Task() = default;
Task(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function); Task(UnlocalizedString unlocalizedName, u64 maxValue, bool background, std::function<void(Task &)> function);
Task(const Task&) = delete; Task(const Task&) = delete;
Task(Task &&other) noexcept; Task(Task &&other) noexcept;
@@ -57,7 +57,6 @@ namespace hex {
void setInterruptCallback(std::function<void()> callback); void setInterruptCallback(std::function<void()> callback);
[[nodiscard]] bool isBackgroundTask() const; [[nodiscard]] bool isBackgroundTask() const;
[[nodiscard]] bool isBlocking() const;
[[nodiscard]] bool isFinished() const; [[nodiscard]] bool isFinished() const;
[[nodiscard]] bool hadException() const; [[nodiscard]] bool hadException() const;
[[nodiscard]] bool wasInterrupted() const; [[nodiscard]] bool wasInterrupted() const;
@@ -85,7 +84,6 @@ namespace hex {
std::atomic<bool> m_shouldInterrupt = false; std::atomic<bool> m_shouldInterrupt = false;
std::atomic<bool> m_background = true; std::atomic<bool> m_background = true;
std::atomic<bool> m_blocking = false;
std::atomic<bool> m_interrupted = false; std::atomic<bool> m_interrupted = false;
std::atomic<bool> m_finished = false; std::atomic<bool> m_finished = false;
@@ -132,55 +130,20 @@ namespace hex {
/** /**
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer * @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
* @param unlocalizedName Name of the task * @param name Name of the task
* @param maxValue Maximum value of the task * @param maxValue Maximum value of the task
* @param function Function to be executed * @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task * @return A TaskHolder holding a weak reference to the task
*/ */
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function); static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
/**
* @brief Creates a new asynchronous task that gets displayed in the Task Manager in the footer
* @param unlocalizedName Name of the task
* @param maxValue Maximum value of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function);
/** /**
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager * @brief Creates a new asynchronous task that does not get displayed in the Task Manager
* @param unlocalizedName Name of the task * @param name Name of the task
* @param function Function to be executed * @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task * @return A TaskHolder holding a weak reference to the task
*/ */
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void(Task &)> function); static TaskHolder createBackgroundTask(std::string name, std::function<void(Task &)> function);
/**
* @brief Creates a new asynchronous task that does not get displayed in the Task Manager
* @param unlocalizedName Name of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createBackgroundTask(const UnlocalizedString &unlocalizedName, std::function<void()> function);
/**
* @brief Creates a new asynchronous task that shows a blocking modal window
* @param unlocalizedName Name of the task
* @param maxValue Maximum value of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
/**
* @brief Creates a new asynchronous task that shows a blocking modal window
* @param unlocalizedName Name of the task
* @param maxValue Maximum value of the task
* @param function Function to be executed
* @return A TaskHolder holding a weak reference to the task
*/
static TaskHolder createBlockingTask(const UnlocalizedString &unlocalizedName, u64 maxValue, std::function<void()> function);
/** /**
* @brief Creates a new synchronous task that will execute the given function at the start of the next frame * @brief Creates a new synchronous task that will execute the given function at the start of the next frame
@@ -222,13 +185,12 @@ namespace hex {
static size_t getRunningTaskCount(); static size_t getRunningTaskCount();
static size_t getRunningBackgroundTaskCount(); static size_t getRunningBackgroundTaskCount();
static size_t getRunningBlockingTaskCount();
static const std::list<std::shared_ptr<Task>>& getRunningTasks(); static const std::list<std::shared_ptr<Task>>& getRunningTasks();
static void runDeferredCalls(); static void runDeferredCalls();
private: private:
static TaskHolder createTask(const UnlocalizedString &unlocalizedName, u64 maxValue, bool background, bool blocking, std::function<void(Task &)> function); static TaskHolder createTask(std::string name, u64 maxValue, bool background, std::function<void(Task &)> function);
}; };
} }

View File

@@ -56,7 +56,6 @@ namespace hex {
*/ */
static void addStyleHandler(const std::string &name, const StyleMap &styleMap); static void addStyleHandler(const std::string &name, const StyleMap &styleMap);
static void reapplyCurrentTheme();
static std::vector<std::string> getThemeNames(); static std::vector<std::string> getThemeNames();
static const std::string &getImageTheme(); static const std::string &getImageTheme();
@@ -67,7 +66,6 @@ namespace hex {
static void reset(); static void reset();
static void setAccentColor(const ImColor &color);
public: public:
struct ThemeHandler { struct ThemeHandler {
@@ -83,7 +81,6 @@ namespace hex {
static const std::map<std::string, ThemeHandler>& getThemeHandlers(); static const std::map<std::string, ThemeHandler>& getThemeHandlers();
static const std::map<std::string, StyleHandler>& getStyleHandlers(); static const std::map<std::string, StyleHandler>& getStyleHandlers();
private: private:
ThemeManager() = default; ThemeManager() = default;
}; };

View File

@@ -119,8 +119,6 @@ namespace hex {
decltype(m_steps)::iterator m_currentStep, m_latestStep; decltype(m_steps)::iterator m_currentStep, m_latestStep;
}; };
static void init();
/** /**
* @brief Gets a list of all tutorials * @brief Gets a list of all tutorials
* @return List of all tutorials * @return List of all tutorials
@@ -147,13 +145,6 @@ namespace hex {
*/ */
static void startTutorial(const UnlocalizedString &unlocalizedName); static void startTutorial(const UnlocalizedString &unlocalizedName);
static void startHelpHover();
static void addInteractiveHelpText(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, UnlocalizedString unlocalizedString);
static void addInteractiveHelpLink(std::initializer_list<std::variant<Lang, std::string, int>> &&ids, std::string link);
static void setLastItemInteractiveHelpPopup(std::function<void()> callback);
static void setLastItemInteractiveHelpLink(std::string link);
/** /**
* @brief Draws the tutorial * @brief Draws the tutorial

View File

@@ -24,8 +24,8 @@ namespace hex {
static void removeWorkspace(const std::string &name); static void removeWorkspace(const std::string &name);
static const std::map<std::string, Workspace>& getWorkspaces(); static const auto& getWorkspaces() { return *s_workspaces; }
static const std::map<std::string, Workspace>::iterator& getCurrentWorkspace(); static const auto& getCurrentWorkspace() { return s_currentWorkspace; }
static void reset(); static void reset();
static void reload(); static void reload();
@@ -34,6 +34,9 @@ namespace hex {
private: private:
WorkspaceManager() = default; WorkspaceManager() = default;
static AutoReset<std::map<std::string, Workspace>> s_workspaces;
static decltype(s_workspaces)::Type::iterator s_currentWorkspace, s_previousWorkspace, s_workspaceToRemove;
}; };
} }

View File

@@ -3,6 +3,7 @@
#include <hex.hpp> #include <hex.hpp>
#include <hex/api/localization_manager.hpp> #include <hex/api/localization_manager.hpp>
#include <hex/helpers/intrinsics.hpp>
#include <hex/data_processor/attribute.hpp> #include <hex/data_processor/attribute.hpp>
#include <set> #include <set>
@@ -11,7 +12,6 @@
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
#include <imgui.h> #include <imgui.h>
#include <hex/providers/provider_data.hpp>
namespace hex::prv { namespace hex::prv {
class Provider; class Provider;
@@ -42,12 +42,11 @@ namespace hex::dp {
m_overlay = overlay; m_overlay = overlay;
} }
void draw(); virtual void drawNode() { }
virtual void process() = 0; virtual void process() = 0;
virtual void reset() { }
virtual void store(nlohmann::json &j) const { std::ignore = j; } virtual void store(nlohmann::json &j) const { hex::unused(j); }
virtual void load(const nlohmann::json &j) { std::ignore = j; } virtual void load(const nlohmann::json &j) { hex::unused(j); }
struct NodeError { struct NodeError {
Node *node; Node *node;
@@ -81,11 +80,6 @@ namespace hex::dp {
void setIntegerOnOutput(u32 index, i128 integer); void setIntegerOnOutput(u32 index, i128 integer);
void setFloatOnOutput(u32 index, double floatingPoint); void setFloatOnOutput(u32 index, double floatingPoint);
static void interrupt();
protected:
virtual void drawNode() { }
private: private:
int m_id; int m_id;
UnlocalizedString m_unlocalizedTitle, m_unlocalizedName; UnlocalizedString m_unlocalizedTitle, m_unlocalizedName;
@@ -96,16 +90,45 @@ namespace hex::dp {
static int s_idCounter; static int s_idCounter;
Attribute& getAttribute(u32 index); Attribute& getAttribute(u32 index) {
Attribute *getConnectedInputAttribute(u32 index); if (index >= this->getAttributes().size())
void markInputProcessed(u32 index); throw std::runtime_error("Attribute index out of bounds!");
void unmarkInputProcessed(u32 index);
return this->getAttributes()[index];
}
Attribute *getConnectedInputAttribute(u32 index) {
const auto &connectedAttribute = this->getAttribute(index).getConnectedAttributes();
if (connectedAttribute.empty())
return nullptr;
return connectedAttribute.begin()->second;
}
void markInputProcessed(u32 index) {
const auto &[iter, inserted] = m_processedInputs.insert(index);
if (!inserted)
throwNodeError("Recursion detected!");
}
void unmarkInputProcessed(u32 index) {
m_processedInputs.erase(index);
}
protected: protected:
[[noreturn]] void throwNodeError(const std::string &message); [[noreturn]] void throwNodeError(const std::string &message) {
throw NodeError { this, message };
}
void setOverlayData(u64 address, const std::vector<u8> &data); void setOverlayData(u64 address, const std::vector<u8> &data);
void setAttributes(std::vector<Attribute> attributes);
void setAttributes(std::vector<Attribute> attributes) {
m_attributes = std::move(attributes);
for (auto &attr : m_attributes)
attr.setParentNode(this);
}
}; };
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <hex/api/event_manager.hpp>
#include <hex/api/imhex_api.hpp> #include <hex/api/imhex_api.hpp>
namespace hex { namespace hex {
@@ -23,20 +24,6 @@ namespace hex {
ImHexApi::System::impl::addAutoResetObject(this); ImHexApi::System::impl::addAutoResetObject(this);
} }
AutoReset(const T &value) : AutoReset() {
m_value = value;
m_valid = true;
}
AutoReset(T &&value) noexcept : AutoReset() {
m_value = std::move(value);
m_valid = true;
}
~AutoReset() {
ImHexApi::System::impl::removeAutoResetObject(this);
}
T* operator->() { T* operator->() {
return &m_value; return &m_value;
} }

View File

@@ -2,15 +2,10 @@
#include <hex.hpp> #include <hex.hpp>
#include <wolv/utils/expected.hpp>
#include <array> #include <array>
#include <string> #include <string>
#include <vector> #include <vector>
#define CRYPTO_ERROR_INVALID_KEY_LENGTH (-1)
#define CRYPTO_ERROR_INVALID_MODE (-2)
namespace hex::prv { namespace hex::prv {
class Provider; class Provider;
} }
@@ -65,5 +60,5 @@ namespace hex::crypt {
Key256Bits = 2 Key256Bits = 2
}; };
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input); std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
} }

View File

@@ -44,7 +44,4 @@ namespace hex::dbg {
} }
} }
bool debugModeEnabled();
void setDebugModeEnabled(bool enabled);
} }

View File

@@ -1,114 +0,0 @@
#pragma once
#include <hex/helpers/fs.hpp>
#include <array>
#include <vector>
namespace hex::paths {
namespace impl {
class DefaultPath {
protected:
constexpr DefaultPath() = default;
virtual ~DefaultPath() = default;
public:
DefaultPath(const DefaultPath&) = delete;
DefaultPath(DefaultPath&&) = delete;
DefaultPath& operator=(const DefaultPath&) = delete;
DefaultPath& operator=(DefaultPath&&) = delete;
virtual std::vector<std::fs::path> all() const = 0;
virtual std::vector<std::fs::path> read() const;
virtual std::vector<std::fs::path> write() const;
};
class ConfigPath : public DefaultPath {
public:
explicit ConfigPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {}
std::vector<std::fs::path> all() const override;
private:
std::fs::path m_postfix;
};
class DataPath : public DefaultPath {
public:
explicit DataPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {}
std::vector<std::fs::path> all() const override;
std::vector<std::fs::path> write() const override;
private:
std::fs::path m_postfix;
};
class PluginPath : public DefaultPath {
public:
explicit PluginPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {}
std::vector<std::fs::path> all() const override;
private:
std::fs::path m_postfix;
};
}
std::vector<std::fs::path> getDataPaths(bool includeSystemFolders);
std::vector<std::fs::path> getConfigPaths(bool includeSystemFolders);
const static inline impl::ConfigPath Config("config");
const static inline impl::ConfigPath Recent("recent");
const static inline impl::PluginPath Libraries("lib");
const static inline impl::PluginPath Plugins("plugins");
const static inline impl::DataPath Patterns("patterns");
const static inline impl::DataPath PatternsInclude("includes");
const static inline impl::DataPath Magic("magic");
const static inline impl::DataPath Yara("yara");
const static inline impl::DataPath YaraAdvancedAnalysis("yara/advanced_analysis");
const static inline impl::DataPath Backups("backups");
const static inline impl::DataPath Resources("resources");
const static inline impl::DataPath Constants("constants");
const static inline impl::DataPath Encodings("encodings");
const static inline impl::DataPath Logs("logs");
const static inline impl::DataPath Scripts("scripts");
const static inline impl::DataPath Inspectors("scripts/inspectors");
const static inline impl::DataPath Themes("themes");
const static inline impl::DataPath Nodes("scripts/nodes");
const static inline impl::DataPath Layouts("layouts");
const static inline impl::DataPath Workspaces("workspaces");
const static inline impl::DataPath Disassemblers("disassemblers");
constexpr static inline std::array<const impl::DefaultPath*, 21> All = {
&Config,
&Recent,
&Libraries,
&Plugins,
&Patterns,
&PatternsInclude,
&Magic,
&Yara,
&YaraAdvancedAnalysis,
&Backups,
&Resources,
&Constants,
&Encodings,
&Logs,
&Scripts,
&Inspectors,
&Themes,
&Nodes,
&Layouts,
&Workspaces,
&Disassemblers
};
}

View File

@@ -1,9 +1,7 @@
#pragma once #pragma once
#include <string_view> #include <string_view>
#include <fmt/core.h> #include <fmt/format.h>
#include <fmt/ranges.h>
#include <fmt/ostream.h>
namespace hex { namespace hex {

View File

@@ -1,5 +1,7 @@
#pragma once #pragma once
#include <hex.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include <filesystem> #include <filesystem>
@@ -29,7 +31,36 @@ namespace hex::fs {
void openFolderExternal(const std::fs::path &dirPath); void openFolderExternal(const std::fs::path &dirPath);
void openFolderWithSelectionExternal(const std::fs::path &selectedFilePath); void openFolderWithSelectionExternal(const std::fs::path &selectedFilePath);
enum class ImHexPath : u32 {
Patterns = 0,
PatternsInclude,
Magic,
Plugins,
Yara,
YaraAdvancedAnalysis,
Config,
Backups,
Resources,
Constants,
Encodings,
Logs,
Recent,
Scripts,
Inspectors,
Themes,
Libraries,
Nodes,
Layouts,
Workspaces,
END
};
bool isPathWritable(const std::fs::path &path); bool isPathWritable(const std::fs::path &path);
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting = false);
// Temporarily expose these for the migration function
std::vector<std::fs::path> getDataPaths();
std::vector<std::fs::path> appendPath(std::vector<std::fs::path> paths, const std::fs::path &folder);
} }

View File

@@ -12,6 +12,10 @@
#if defined(OS_WEB) #if defined(OS_WEB)
#include <emscripten/fetch.h> #include <emscripten/fetch.h>
using curl_off_t = long;
#else
#include <curl/curl.h>
#endif #endif
typedef void CURL; typedef void CURL;
@@ -117,18 +121,18 @@ namespace hex {
static std::string urlDecode(const std::string &input); static std::string urlDecode(const std::string &input);
void setProgress(float progress) { m_progress = progress; } protected:
bool isCanceled() const { return m_canceled; } void setDefaultConfig();
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);
template<typename T> template<typename T>
Result<T> executeImpl(std::vector<u8> &data); Result<T> executeImpl(std::vector<u8> &data);
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: private:
static void checkProxyErrors(); static void checkProxyErrors();
void setDefaultConfig();
private: private:
#if defined(OS_WEB) #if defined(OS_WEB)

View File

@@ -25,16 +25,13 @@
template<typename T> template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) { std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
std::ignore = path; hex::unused(path, mimeName);
std::ignore = mimeName;
throw std::logic_error("Not implemented"); throw std::logic_error("Not implemented");
} }
template<typename T> template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) { std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
std::ignore = data; hex::unused(data, mimeName, fileName);
std::ignore = mimeName;
std::ignore = fileName;
throw std::logic_error("Not implemented"); throw std::logic_error("Not implemented");
} }

View File

@@ -5,6 +5,8 @@
#include <string> #include <string>
#include <future> #include <future>
#include <curl/curl.h>
#include <hex/helpers/logger.hpp> #include <hex/helpers/logger.hpp>
#include <hex/helpers/fmt.hpp> #include <hex/helpers/fmt.hpp>
@@ -12,26 +14,14 @@
namespace hex { namespace hex {
namespace impl {
void setWriteFunctions(CURL *curl, wolv::io::File &file);
void setWriteFunctions(CURL *curl, std::vector<u8> &data);
void setupFileUpload(CURL *curl, wolv::io::File &file, const std::string &fileName, const std::string &mimeName);
void setupFileUpload(CURL *curl, const std::vector<u8> &data, const std::fs::path &fileName, const std::string &mimeName);
int executeCurl(CURL *curl, const std::string &url, const std::string &method, const std::string &body, std::map<std::string, std::string> &headers);
long getStatusCode(CURL *curl);
std::string getStatusText(int result);
}
template<typename T> template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) { std::future<HttpRequest::Result<T>> HttpRequest::downloadFile(const std::fs::path &path) {
return std::async(std::launch::async, [this, path] { return std::async(std::launch::async, [this, path] {
std::vector<u8> response; std::vector<u8> response;
wolv::io::File file(path, wolv::io::File::Mode::Create); wolv::io::File file(path, wolv::io::File::Mode::Create);
impl::setWriteFunctions(m_curl, file); curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToFile);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &file);
return this->executeImpl<T>(response); return this->executeImpl<T>(response);
}); });
@@ -41,12 +31,40 @@
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) { std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(const std::fs::path &path, const std::string &mimeName) {
return std::async(std::launch::async, [this, path, mimeName]{ return std::async(std::launch::async, [this, path, mimeName]{
auto fileName = wolv::util::toUTF8String(path.filename()); auto fileName = wolv::util::toUTF8String(path.filename());
curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
wolv::io::File file(path, wolv::io::File::Mode::Read); wolv::io::File file(path, wolv::io::File::Mode::Read);
impl::setupFileUpload(m_curl, file, fileName, mimeName); curl_mime_data_cb(part, file.getSize(),
[](char *buffer, size_t size, size_t nitems, void *arg) -> size_t {
auto handle = static_cast<FILE*>(arg);
return fread(buffer, size, nitems, handle);
},
[](void *arg, curl_off_t offset, int origin) -> int {
auto handle = static_cast<FILE*>(arg);
if (fseek(handle, offset, origin) != 0)
return CURL_SEEKFUNC_CANTSEEK;
else
return CURL_SEEKFUNC_OK;
},
[](void *arg) {
auto handle = static_cast<FILE*>(arg);
fclose(handle);
},
file.getHandle());
curl_mime_filename(part, fileName.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
std::vector<u8> responseData; std::vector<u8> responseData;
impl::setWriteFunctions(m_curl, responseData); curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData); return this->executeImpl<T>(responseData);
}); });
@@ -55,10 +73,19 @@
template<typename T> template<typename T>
std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) { std::future<HttpRequest::Result<T>> HttpRequest::uploadFile(std::vector<u8> data, const std::string &mimeName, const std::fs::path &fileName) {
return std::async(std::launch::async, [this, data = std::move(data), mimeName, fileName]{ return std::async(std::launch::async, [this, data = std::move(data), mimeName, fileName]{
impl::setupFileUpload(m_curl, data, fileName, mimeName); curl_mime *mime = curl_mime_init(m_curl);
curl_mimepart *part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char *>(data.data()), data.size());
auto fileNameStr = wolv::util::toUTF8String(fileName.filename());
curl_mime_filename(part, fileNameStr.c_str());
curl_mime_name(part, mimeName.c_str());
curl_easy_setopt(m_curl, CURLOPT_MIMEPOST, mime);
std::vector<u8> responseData; std::vector<u8> responseData;
impl::setWriteFunctions(m_curl, responseData); curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData); return this->executeImpl<T>(responseData);
}); });
@@ -69,7 +96,8 @@
return std::async(std::launch::async, [this] { return std::async(std::launch::async, [this] {
std::vector<u8> responseData; std::vector<u8> responseData;
impl::setWriteFunctions(m_curl, responseData); curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, writeToVector);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &responseData);
return this->executeImpl<T>(responseData); return this->executeImpl<T>(responseData);
}); });
@@ -77,16 +105,43 @@
template<typename T> template<typename T>
HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) { HttpRequest::Result<T> HttpRequest::executeImpl(std::vector<u8> &data) {
curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, m_method.c_str());
setDefaultConfig(); setDefaultConfig();
std::scoped_lock lock(m_transmissionMutex); if (!m_body.empty()) {
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, m_body.c_str());
if (auto result = impl::executeCurl(m_curl, m_url, m_method, m_body, m_headers); result != 0) {
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, m_url, u32(result), impl::getStatusText(result));
checkProxyErrors();
} }
return Result<T>(impl::getStatusCode(m_curl), { data.begin(), data.end() }); curl_slist *headers = nullptr;
headers = curl_slist_append(headers, "Cache-Control: no-cache");
ON_SCOPE_EXIT { curl_slist_free_all(headers); };
for (auto &[key, value] : m_headers) {
std::string header = hex::format("{}: {}", key, value);
headers = curl_slist_append(headers, header.c_str());
}
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
{
std::scoped_lock lock(m_transmissionMutex);
auto result = curl_easy_perform(m_curl);
if (result != CURLE_OK){
char *url = nullptr;
curl_easy_getinfo(m_curl, CURLINFO_EFFECTIVE_URL, &url);
log::error("Http request '{0} {1}' failed with error {2}: '{3}'", m_method, url, u32(result), curl_easy_strerror(result));
checkProxyErrors();
return { };
}
}
long statusCode = 0;
curl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &statusCode);
return Result<T>(statusCode, { data.begin(), data.end() });
} }
} }

View File

@@ -0,0 +1,9 @@
#pragma once
namespace hex {
void unused(auto && ... x) {
((void)x, ...);
}
}

View File

@@ -1,124 +0,0 @@
#pragma once
#if defined(__cplusplus)
enum class Keys {
#else
enum Keys {
#endif
Invalid,
Space,
Apostrophe,
Comma,
Minus,
Period,
Slash,
Num0,
Num1,
Num2,
Num3,
Num4,
Num5,
Num6,
Num7,
Num8,
Num9,
Semicolon,
Equals,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
LeftBracket,
Backslash,
RightBracket,
GraveAccent,
World1,
World2,
Escape,
Enter,
Tab,
Backspace,
Insert,
Delete,
Right,
Left,
Down,
Up,
PageUp,
PageDown,
Home,
End,
CapsLock,
ScrollLock,
NumLock,
PrintScreen,
Pause,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
F25,
KeyPad0,
KeyPad1,
KeyPad2,
KeyPad3,
KeyPad4,
KeyPad5,
KeyPad6,
KeyPad7,
KeyPad8,
KeyPad9,
KeyPadDecimal,
KeyPadDivide,
KeyPadMultiply,
KeyPadSubtract,
KeyPadAdd,
KeyPadEnter,
KeyPadEqual,
Menu
};
enum Keys scanCodeToKey(int scanCode);
int keyToScanCode(enum Keys key);

View File

@@ -9,9 +9,9 @@
#include <map> #include <map>
#include <span> #include <span>
#include <string> #include <string>
#include <numbers>
#include <opengl_support.h> #include <opengl_support.h>
#include <GLFW/glfw3.h>
#include "imgui.h" #include "imgui.h"
namespace hex::gl { namespace hex::gl {
@@ -188,43 +188,43 @@ namespace hex::gl {
T &getElement(int row,int col) { T &getElement(int row,int col) {
return this->mat[row * Columns+col]; return this->mat[row*Columns+col];
} }
Vector<T,Rows> getColumn(int col) { Vector<T,Rows> getColumn(int col) {
Vector<T,Rows> result; Vector<T,Rows> result;
for (size_t i = 0; i < Rows; i++) for (size_t i = 0; i < Rows; i++)
result[i] = this->mat[i * Columns + col]; result[i] = this->mat[i*Columns+col];
return result; return result;
} }
Vector<T,Columns> getRow(int row) { Vector<T,Columns> getRow(int row) {
Vector<T,Columns> result; Vector<T,Columns> result;
for (size_t i = 0; i < Columns; i++) for (size_t i = 0; i < Columns; i++)
result[i] = this->mat[row * Columns+i]; result[i] = this->mat[row*Columns+i];
return result; return result;
} }
void updateRow(int row, Vector<T,Columns> values) { void updateRow(int row, Vector<T,Columns> values) {
for (size_t i = 0; i < Columns; i++) for (size_t i = 0; i < Columns; i++)
this->mat[row * Columns + i] = values[i]; this->mat[row*Columns+i] = values[i];
} }
void updateColumn(int col, Vector<T,Rows> values) { void updateColumn(int col, Vector<T,Rows> values) {
for (size_t i = 0; i < Rows; i++) for (size_t i = 0; i < Rows; i++)
this->mat[i * Columns + col] = values[i]; this->mat[i*Columns+col] = values[i];
} }
void updateElement(int row, int col, T value) { void updateElement( int row,int col, T value) {
this->mat[row * Columns + col] = value; this->mat[row*Columns + col] = value;
} }
T &operator()(const unsigned &row, const unsigned &col) { T &operator()( const int &row,const int &col) {
return this->mat[row * Columns + col]; return this->mat[row*Columns + col];
} }
const T &operator()(const unsigned &row, const unsigned &col) const { const T &operator()(const unsigned& row,const unsigned& col ) const {
return this->mat[row * Columns + col]; return this->mat[row*Columns + col];
} }
Matrix& operator=(const Matrix& A) { Matrix& operator=(const Matrix& A) {
@@ -242,7 +242,7 @@ namespace hex::gl {
for (size_t i = 0; i < Rows; i++) for (size_t i = 0; i < Rows; i++)
for (size_t j = 0; j < Columns; j++) for (size_t j = 0; j < Columns; j++)
result(i, j) = this->mat[i * Columns + j] + A(i, j); result(i, j) = this->mat[i*Columns+j] + A(i, j);
return result; return result;
} }
@@ -251,7 +251,7 @@ namespace hex::gl {
for (size_t i = 0; i < Rows; i++) for (size_t i = 0; i < Rows; i++)
for (size_t j = 0; j < Columns; j++) for (size_t j = 0; j < Columns; j++)
result(i, j) = this->mat[i * Columns + j] - A(i, j); result(i, j) = this->mat[i*Columns+j] - A(i, j);
return result; return result;
} }
@@ -268,7 +268,7 @@ namespace hex::gl {
Matrix t(0); Matrix t(0);
for (size_t i = 0; i < Columns; i++) for (size_t i = 0; i < Columns; i++)
for (size_t j = 0; j < Rows; j++) for (size_t j = 0; j < Rows; j++)
t.updateElement(i, j, this->mat[j * Rows + i]); t.updateElement(i, j, this->mat[j*Rows+i]);
return t; return t;
} }
@@ -400,8 +400,8 @@ namespace hex::gl {
T Sx, Cx, Sy, Cy, Sz, Cz; T Sx, Cx, Sy, Cy, Sz, Cz;
Vector<T,3> angles = ypr; Vector<T,3> angles = ypr;
if (!radians) if(!radians)
angles *= std::numbers::pi_v<T> / 180; angles *= M_PI/180;
Sx = -sin(angles[0]); Cx = cos(angles[0]); Sx = -sin(angles[0]); Cx = cos(angles[0]);
Sy = -sin(angles[1]); Cy = cos(angles[1]); Sy = -sin(angles[1]); Cy = cos(angles[1]);
@@ -524,7 +524,7 @@ namespace hex::gl {
Vector<T,3> rotationVector3 = {{rotationVector[0], rotationVector[1], rotationVector[2]}}; Vector<T,3> rotationVector3 = {{rotationVector[0], rotationVector[1], rotationVector[2]}};
T theta = rotationVector3.magnitude(); T theta = rotationVector3.magnitude();
if (!radians) if (!radians)
theta *= std::numbers::pi / 180; theta *= M_PI / 180;
Vector<T,3> axis = rotationVector3; Vector<T,3> axis = rotationVector3;
if (theta != 0) if (theta != 0)
axis = axis.normalize(); axis = axis.normalize();
@@ -807,18 +807,16 @@ namespace hex::gl {
void bind() const; void bind() const;
void unbind() const; void unbind() const;
bool isValid() const { return m_program != 0; }
void setUniform(std::string_view name, const int &value); void setUniform(std::string_view name, const int &value);
void setUniform(std::string_view name, const float &value); void setUniform(std::string_view name, const float &value);
template<size_t N> template<size_t N>
void setUniform(std::string_view name, const Vector<float, N> &value) { void setUniform(std::string_view name, const Vector<float, N> &value) {
if constexpr (N == 2) if (N == 2)
glUniform2f(getUniformLocation(name), value[0], value[1]); glUniform2f(getUniformLocation(name), value[0], value[1]);
else if constexpr (N == 3) else if (N == 3)
glUniform3f(getUniformLocation(name), value[0], value[1], value[2]); glUniform3f(getUniformLocation(name), value[0], value[1], value[2]);
else if constexpr (N == 4) else if (N == 4)
glUniform4f(getUniformLocation(name), value[0], value[1], value[2],value[3]); glUniform4f(getUniformLocation(name), value[0], value[1], value[2],value[3]);
} }

View File

@@ -21,11 +21,6 @@ namespace hex {
MissingEOF MissingEOF
}; };
enum class PatchKind {
IPS,
IPS32
};
class Patches { class Patches {
public: public:
Patches() = default; Patches() = default;

View File

@@ -1,36 +0,0 @@
#pragma once
#include <hex.hpp>
#include <compare>
#include <string>
#include <vector>
namespace hex {
class SemanticVersion {
public:
SemanticVersion() = default;
SemanticVersion(std::string version);
SemanticVersion(std::string_view version);
SemanticVersion(const char *version);
std::strong_ordering operator<=>(const SemanticVersion &) const;
bool operator==(const SemanticVersion &other) const;
u32 major() const;
u32 minor() const;
u32 patch() const;
bool nightly() const;
const std::string& buildType() const;
bool isValid() const;
std::string get(bool withBuildType = true) const;
private:
std::vector<std::string> m_parts;
std::string m_buildType;
};
}

View File

@@ -29,7 +29,7 @@ namespace hex {
void close(); void close();
/** /**
* @brief get the error string explaining the error that occurred when opening the file. * @brief get the error string explaining the error that occured when opening the file.
* This error is a combination of the tar error and the native file open error * This error is a combination of the tar error and the native file open error
*/ */
std::string getOpenErrorString() const; std::string getOpenErrorString() const;

View File

@@ -4,12 +4,18 @@
#include <cstdint> #include <cstdint>
#include <concepts> #include <concepts>
#include <type_traits>
#include <wolv/types.hpp> using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using u128 = __uint128_t;
using namespace wolv::unsigned_integers; using i8 = std::int8_t;
using namespace wolv::signed_integers; using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;
using color_t = u32; using color_t = u32;
@@ -55,10 +61,6 @@ namespace hex {
constexpr static Region Invalid() { constexpr static Region Invalid() {
return { 0, 0 }; return { 0, 0 };
} }
constexpr bool operator<(const Region &other) const {
return this->address < other.address;
}
}; };

View File

@@ -26,7 +26,7 @@
#include <hex/helpers/utils_linux.hpp> #include <hex/helpers/utils_linux.hpp>
#endif #endif
#include <imgui.h> struct ImVec2;
namespace hex { namespace hex {
@@ -34,29 +34,6 @@ namespace hex {
class Provider; class Provider;
} }
template<typename T>
[[nodiscard]] std::vector<std::vector<T>> sampleChannels(const std::vector<T> &data, size_t count, size_t channels) {
if (channels == 0) return {};
size_t signalLength = std::max<double>(1.0, double(data.size()) / channels);
size_t stride = std::max(1.0, double(signalLength) / count);
std::vector<std::vector<T>> result;
result.resize(channels);
for (size_t i = 0; i < channels; i++) {
result[i].reserve(count);
}
result.reserve(count);
for (size_t i = 0; i < data.size(); i += stride) {
for (size_t j = 0; j < channels; j++) {
result[j].push_back(data[i + j]);
}
}
return result;
}
template<typename T> template<typename T>
[[nodiscard]] std::vector<T> sampleData(const std::vector<T> &data, size_t count) { [[nodiscard]] std::vector<T> sampleData(const std::vector<T> &data, size_t count) {
size_t stride = std::max(1.0, double(data.size()) / count); size_t stride = std::max(1.0, double(data.size()) / count);
@@ -109,13 +86,13 @@ namespace hex {
[[nodiscard]] std::wstring utf8ToUtf16(const std::string& utf8); [[nodiscard]] std::wstring utf8ToUtf16(const std::string& utf8);
[[nodiscard]] std::string utf16ToUtf8(const std::wstring& utf16); [[nodiscard]] std::string utf16ToUtf8(const std::wstring& utf16);
[[nodiscard]] constexpr u64 extract(u8 from, u8 to, const auto &value) { [[nodiscard]] constexpr u64 extract(u8 from, u8 to, const std::unsigned_integral auto &value) {
if (from < to) std::swap(from, to); if (from < to) std::swap(from, to);
using ValueType = std::remove_cvref_t<decltype(value)>; using ValueType = std::remove_cvref_t<decltype(value)>;
ValueType mask = (std::numeric_limits<ValueType>::max() >> (((sizeof(value) * 8) - 1) - (from - to))) << to; ValueType mask = (std::numeric_limits<ValueType>::max() >> (((sizeof(value) * 8) - 1) - (from - to))) << to;
return u64((value & mask) >> to); return (value & mask) >> to;
} }
[[nodiscard]] inline u64 extract(u32 from, u32 to, const std::vector<u8> &bytes) { [[nodiscard]] inline u64 extract(u32 from, u32 to, const std::vector<u8> &bytes) {
@@ -278,20 +255,20 @@ namespace hex {
std::string result; std::string result;
for (i16 bit = hex::bit_width(number) - 1; bit >= 0; bit -= 1) for (i16 bit = hex::bit_width(number) - 1; bit >= 0; bit -= 1)
result += (number & (0b1LLU << bit)) == 0 ? '0' : '1'; result += (number & (0b1 << bit)) == 0 ? '0' : '1';
return result; return result;
} }
[[nodiscard]] float float16ToFloat32(u16 float16); [[nodiscard]] float float16ToFloat32(u16 float16);
[[nodiscard]] inline bool equalsIgnoreCase(std::string_view left, std::string_view right) { [[nodiscard]] inline bool equalsIgnoreCase(const std::string &left, const std::string &right) {
return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) { return std::equal(left.begin(), left.end(), right.begin(), right.end(), [](char a, char b) {
return tolower(a) == tolower(b); return tolower(a) == tolower(b);
}); });
} }
[[nodiscard]] inline bool containsIgnoreCase(std::string_view a, std::string_view b) { [[nodiscard]] inline bool containsIgnoreCase(const std::string &a, const std::string &b) {
auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) { auto iter = std::search(a.begin(), a.end(), b.begin(), b.end(), [](char ch1, char ch2) {
return std::toupper(ch1) == std::toupper(ch2); return std::toupper(ch1) == std::toupper(ch2);
}); });
@@ -321,7 +298,31 @@ namespace hex {
[[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env); [[nodiscard]] std::optional<std::string> getEnvironmentVariable(const std::string &env);
[[nodiscard]] std::string limitStringLength(const std::string &string, size_t maxLength); [[nodiscard]] inline std::string limitStringLength(const std::string &string, size_t maxLength) {
// If the string is shorter than the max length, return it as is
if (string.size() < maxLength)
return string;
// If the string is longer than the max length, find the last space before the max length
auto it = string.begin() + maxLength;
while (it != string.begin() && !std::isspace(*it)) --it;
// If there's no space before the max length, just cut the string
if (it == string.begin()) {
it = string.begin() + maxLength;
// Try to find a UTF-8 character boundary
while (it != string.begin() && (*it & 0x80) != 0x00) --it;
++it;
}
// If we still didn't find a valid boundary, just return the string as is
if (it == string.begin())
return string;
// Append
return std::string(string.begin(), it) + "";
}
[[nodiscard]] std::optional<std::fs::path> getInitialFilePath(); [[nodiscard]] std::optional<std::fs::path> getInitialFilePath();
@@ -340,6 +341,4 @@ namespace hex {
*/ */
[[nodiscard]] void* getContainingModule(void* symbol); [[nodiscard]] void* getContainingModule(void* symbol);
[[nodiscard]] std::optional<ImColor> blendColors(const std::optional<ImColor> &a, const std::optional<ImColor> &b);
} }

View File

@@ -1,7 +1,5 @@
#pragma once #pragma once
#include <hex/helpers/keys.hpp>
#if defined(OS_MACOS) #if defined(OS_MACOS)
struct GLFWwindow; struct GLFWwindow;
@@ -19,15 +17,7 @@
void enumerateFontsMacos(); void enumerateFontsMacos();
void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window); void macosHandleTitlebarDoubleClickGesture(GLFWwindow *window);
void macosSetWindowMovable(GLFWwindow *window, bool movable);
bool macosIsWindowBeingResizedByUser(GLFWwindow *window); bool macosIsWindowBeingResizedByUser(GLFWwindow *window);
void macosMarkContentEdited(GLFWwindow *window, bool edited = true);
void macosGetKey(Keys key, int *output);
bool macosIsMainInstance();
void macosSendMessageToMainInstance(const unsigned char *data, size_t size);
void macosInstallEventListener();
} }
#endif #endif

View File

@@ -13,13 +13,6 @@
#include <wolv/utils/preproc.hpp> #include <wolv/utils/preproc.hpp>
#include <wolv/utils/guards.hpp> #include <wolv/utils/guards.hpp>
#if defined(_MSC_VER)
#include <windows.h>
#define PLUGIN_ENTRY_POINT extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return TRUE; }
#else
#define PLUGIN_ENTRY_POINT
#endif
namespace { namespace {
struct PluginFunctionHelperInstantiation {}; struct PluginFunctionHelperInstantiation {};
} }
@@ -44,51 +37,28 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
return nullptr; return nullptr;
} }
[[maybe_unused]] static auto& getFeaturesImpl() {
static std::vector<hex::Feature> features;
return features;
}
#if defined (IMHEX_STATIC_LINK_PLUGINS) #if defined (IMHEX_STATIC_LINK_PLUGINS)
#define IMHEX_PLUGIN_VISIBILITY_PREFIX static #define IMHEX_PLUGIN_VISIBILITY_PREFIX static
#else #else
#if defined(_MSC_VER) #define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" __declspec(dllexport)
#else
#define IMHEX_PLUGIN_VISIBILITY_PREFIX extern "C" [[gnu::visibility("default")]]
#endif
#endif #endif
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
#define IMHEX_DEFINE_PLUGIN_FEATURES() IMHEX_DEFINE_PLUGIN_FEATURES_IMPL()
#define IMHEX_DEFINE_PLUGIN_FEATURES_IMPL() \
template<> \
struct PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation> { \
static void* getFeatures(); \
}; \
void* PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures() { \
return &getFeaturesImpl(); \
} \
static auto initFeatures = [] { getFeaturesImpl() = std::vector<hex::Feature>({ IMHEX_PLUGIN_FEATURES_CONTENT }); return 0; }()
#define IMHEX_PLUGIN_FEATURES ::getFeaturesImpl()
/** /**
* This macro is used to define all the required entry points for a plugin. * This macro is used to define all the required entry points for a plugin.
* Name, Author and Description will be displayed in the plugin list on the Welcome screen. * Name, Author and Description will be displayed in the in the plugin list on the Welcome screen.
*/ */
#define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(name, author, description) #define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(name, author, description)
#define IMHEX_LIBRARY_SETUP(name) IMHEX_LIBRARY_SETUP_IMPL(name) #define IMHEX_LIBRARY_SETUP(name) IMHEX_LIBRARY_SETUP_IMPL(name)
#define IMHEX_LIBRARY_SETUP_IMPL(name) \ #define IMHEX_LIBRARY_SETUP_IMPL(name) \
namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::info("Unloaded library '{}'", name); } } HANDLER; } \ namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::debug("Unloaded library '{}'", name); } } HANDLER; } \
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)(); \ IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)(); \
IMHEX_PLUGIN_VISIBILITY_PREFIX const char *WOLV_TOKEN_CONCAT(getLibraryName_, IMHEX_PLUGIN_NAME)() { return name; } \ IMHEX_PLUGIN_VISIBILITY_PREFIX const char *WOLV_TOKEN_CONCAT(getLibraryName_, IMHEX_PLUGIN_NAME)() { return name; } \
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(setImGuiContext_, IMHEX_PLUGIN_NAME)(ImGuiContext *ctx) { \ IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(setImGuiContext_, IMHEX_PLUGIN_NAME)(ImGuiContext *ctx) { \
ImGui::SetCurrentContext(ctx); \ ImGui::SetCurrentContext(ctx); \
GImGui = ctx; \ GImGui = ctx; \
} \ } \
extern "C" void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \ extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
hex::PluginManager::addPlugin(name, hex::PluginFunctions { \ hex::PluginManager::addPlugin(name, hex::PluginFunctions { \
nullptr, \ nullptr, \
WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME), \ WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME), \
@@ -103,7 +73,6 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
nullptr \ nullptr \
}); \ }); \
} \ } \
PLUGIN_ENTRY_POINT \
IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)() IMHEX_PLUGIN_VISIBILITY_PREFIX void WOLV_TOKEN_CONCAT(initializeLibrary_, IMHEX_PLUGIN_NAME)()
#define IMHEX_PLUGIN_SETUP_IMPL(name, author, description) \ #define IMHEX_PLUGIN_SETUP_IMPL(name, author, description) \
@@ -116,7 +85,6 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
ImGui::SetCurrentContext(ctx); \ ImGui::SetCurrentContext(ctx); \
GImGui = ctx; \ GImGui = ctx; \
} \ } \
IMHEX_DEFINE_PLUGIN_FEATURES(); \
IMHEX_PLUGIN_VISIBILITY_PREFIX void* getFeatures() { \ IMHEX_PLUGIN_VISIBILITY_PREFIX void* getFeatures() { \
return PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures(); \ return PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures(); \
} \ } \
@@ -124,7 +92,7 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
return PluginSubCommandsFunctionHelper<PluginFunctionHelperInstantiation>::getSubCommands(); \ return PluginSubCommandsFunctionHelper<PluginFunctionHelperInstantiation>::getSubCommands(); \
} \ } \
IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin(); \ IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin(); \
extern "C" void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \ extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \
hex::PluginManager::addPlugin(name, hex::PluginFunctions { \ hex::PluginManager::addPlugin(name, hex::PluginFunctions { \
initializePlugin, \ initializePlugin, \
nullptr, \ nullptr, \
@@ -139,7 +107,6 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
getFeatures \ getFeatures \
}); \ }); \
} \ } \
PLUGIN_ENTRY_POINT \
IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin() IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin()
/** /**
@@ -162,3 +129,18 @@ void* PluginSubCommandsFunctionHelper<T>::getSubCommands() {
return &g_subCommands; \ return &g_subCommands; \
} \ } \
std::vector<hex::SubCommand> g_subCommands std::vector<hex::SubCommand> g_subCommands
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
#define IMHEX_DEFINE_PLUGIN_FEATURES() IMHEX_DEFINE_PLUGIN_FEATURES_IMPL()
#define IMHEX_DEFINE_PLUGIN_FEATURES_IMPL() \
extern std::vector<hex::Feature> g_features; \
template<> \
struct PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation> { \
static void* getFeatures(); \
}; \
void* PluginFeatureFunctionHelper<PluginFunctionHelperInstantiation>::getFeatures() { \
return &g_features; \
} \
std::vector<hex::Feature> g_features
#define IMHEX_PLUGIN_FEATURES g_features

View File

@@ -1,57 +0,0 @@
#pragma once
#include <hex.hpp>
#include <hex/api/localization_manager.hpp>
#include <memory>
#include <list>
#include <string>
namespace hex::proj {
class Content {
public:
explicit Content(UnlocalizedString type, std::string name)
: m_type(std::move(type)), m_name(std::move(name)) { }
void setData(std::string data) { m_data = std::move(data); }
const std::string& getData() const { return m_data; }
const std::string& getName() const { return m_name; }
void setName(std::string name) { m_name = std::move(name); }
const UnlocalizedString& getType() const { return m_type; }
bool isOpen() const { return m_open; }
void setOpen(bool open) { m_open = open; }
bool isEmpty() const { return m_data.empty(); }
private:
UnlocalizedString m_type;
std::string m_name;
std::string m_data;
bool m_open = false;
};
class Project {
public:
explicit Project(std::string name) : m_name(std::move(name)) {}
Project(const Project &) = delete;
Project(Project &&) = delete;
~Project();
Project &operator=(const Project &) = delete;
Project &operator=(Project &&) = delete;
const std::string &getName() const { return m_name; }
void addContent(UnlocalizedString type);
const std::list<std::unique_ptr<Content>>& getContents() const { return m_contents; }
private:
std::string m_name;
std::list<std::unique_ptr<Content>> m_contents;
};
}

View File

@@ -1,43 +0,0 @@
#pragma once
#include <hex.hpp>
#include <hex/project/project.hpp>
#include <list>
#include <string>
#include <filesystem>
#include <functional>
namespace hex::proj {
class ProjectManager {
ProjectManager() = default;
public:
static void createProject(std::string name);
static void loadProject(const std::filesystem::path &path);
static void removeProject(const Project &project);
using LoadFunction = std::function<void(const Content&)>;
using StoreFunction = std::function<void(Content&)>;
struct ContentHandler {
UnlocalizedString type;
bool allowMultiple = false;
LoadFunction load;
StoreFunction store;
};
static void registerContentHandler(ContentHandler handler);
static const std::list<ContentHandler>& getContentHandlers();
static const ContentHandler* getContentHandler(const UnlocalizedString &typeName);
static const std::list<std::unique_ptr<Project>> &getProjects();
static void storeContent(Content &content);
static void loadContent(Content &content);
static Content* getLoadedContent(const UnlocalizedString &type);
};
}

View File

@@ -38,7 +38,7 @@ namespace hex::prv {
[[nodiscard]] std::string getName() const override { return m_name; } [[nodiscard]] std::string getName() const override { return m_name; }
[[nodiscard]] UnlocalizedString getTypeName() const override { return "MemoryProvider"; } [[nodiscard]] std::string getTypeName() const override { return "MemoryProvider"; }
private: private:
void renameFile(); void renameFile();

View File

@@ -30,7 +30,6 @@ namespace hex::prv {
struct MenuEntry { struct MenuEntry {
std::string name; std::string name;
const char *icon;
std::function<void()> callback; std::function<void()> callback;
}; };
@@ -114,7 +113,7 @@ namespace hex::prv {
* @param size number of bytes to read * @param size number of bytes to read
* @param overlays apply overlays and patches is true. Same as readRaw() if false * @param overlays apply overlays and patches is true. Same as readRaw() if false
*/ */
virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true); void read(u64 offset, void *buffer, size_t size, bool overlays = true);
/** /**
* @brief Write data to the patches of this provider. Will not directly modify provider. * @brief Write data to the patches of this provider. Will not directly modify provider.
@@ -122,7 +121,7 @@ namespace hex::prv {
* @param buffer buffer to take data to write from * @param buffer buffer to take data to write from
* @param size number of bytes to write * @param size number of bytes to write
*/ */
virtual void write(u64 offset, const void *buffer, size_t size); void write(u64 offset, const void *buffer, size_t size);
/** /**
* @brief Read data from this provider, without applying overlays and patches * @brief Read data from this provider, without applying overlays and patches
@@ -152,7 +151,7 @@ namespace hex::prv {
* like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file" * like "hex.builtin.provider.mem_file" or "hex.builtin.provider.file"
* @return The provider's type name * @return The provider's type name
*/ */
[[nodiscard]] virtual UnlocalizedString getTypeName() const = 0; [[nodiscard]] virtual std::string getTypeName() const = 0;
/** /**
* @brief Gets a human readable representation of the current provider * @brief Gets a human readable representation of the current provider
@@ -166,7 +165,7 @@ namespace hex::prv {
void insert(u64 offset, u64 size); void insert(u64 offset, u64 size);
void remove(u64 offset, u64 size); void remove(u64 offset, u64 size);
virtual void resizeRaw(u64 newSize) { std::ignore = newSize; } virtual void resizeRaw(u64 newSize) { hex::unused(newSize); }
virtual void insertRaw(u64 offset, u64 size); virtual void insertRaw(u64 offset, u64 size);
virtual void removeRaw(u64 offset, u64 size); virtual void removeRaw(u64 offset, u64 size);
@@ -194,11 +193,11 @@ namespace hex::prv {
[[nodiscard]] virtual std::vector<Description> getDataDescription() const; [[nodiscard]] virtual std::vector<Description> getDataDescription() const;
[[nodiscard]] virtual std::variant<std::string, i128> queryInformation(const std::string &category, const std::string &argument); [[nodiscard]] virtual std::variant<std::string, i128> queryInformation(const std::string &category, const std::string &argument);
virtual void undo(); void undo();
virtual void redo(); void redo();
[[nodiscard]] virtual bool canUndo() const; [[nodiscard]] bool canUndo() const;
[[nodiscard]] virtual bool canRedo() const; [[nodiscard]] bool canRedo() const;
[[nodiscard]] virtual bool hasFilePicker() const; [[nodiscard]] virtual bool hasFilePicker() const;
virtual bool handleFilePicker(); virtual bool handleFilePicker();
@@ -232,7 +231,7 @@ namespace hex::prv {
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...); return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
} }
[[nodiscard]] virtual undo::Stack& getUndoStack() { return m_undoRedoStack; } [[nodiscard]] undo::Stack& getUndoStack() { return m_undoRedoStack; }
protected: protected:
u32 m_currPage = 0; u32 m_currPage = 0;

View File

@@ -1,10 +1,7 @@
#pragma once #pragma once
#include <hex/api/imhex_api.hpp> #include <hex/api/imhex_api.hpp>
#include <hex/api/events/events_provider.hpp> #include <hex/api/event_manager.hpp>
#include <hex/api/events/events_lifecycle.hpp>
#include <hex/api/events/requests_provider.hpp>
#include <map> #include <map>
#include <ranges> #include <ranges>

Some files were not shown because too many files have changed in this diff Show More