mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
677036fb9c | ||
|
|
8ccb300ea7 | ||
|
|
dff6e09e1c | ||
|
|
fe1ab12fec | ||
|
|
b17808c6c7 | ||
|
|
6b22464771 | ||
|
|
79ace0a106 | ||
|
|
1770235648 | ||
|
|
f325d50ab8 | ||
|
|
c61e807f13 | ||
|
|
7d0d8d5649 | ||
|
|
318e42be26 | ||
|
|
df26127f88 | ||
|
|
afcd39e162 | ||
|
|
f0c544e7c6 | ||
|
|
aec2626d73 | ||
|
|
23085aee6d | ||
|
|
0ee4b1e336 | ||
|
|
a05d09ffea | ||
|
|
9cd7b746a6 | ||
|
|
78b3f5aef1 | ||
|
|
e25d98ef63 | ||
|
|
bbeb7289c1 | ||
|
|
51474b2eae | ||
|
|
9bf9788689 | ||
|
|
b372d20ab0 | ||
|
|
d1ce8a5f9b | ||
|
|
41ce0f57ed | ||
|
|
1a0b0e2385 | ||
|
|
443dedd832 | ||
|
|
caf9ee0c58 | ||
|
|
b2a9965617 | ||
|
|
821eb4568e | ||
|
|
883207bc6b | ||
|
|
15e38e1012 | ||
|
|
8a36897fd9 | ||
|
|
3e736b36b6 | ||
|
|
2e90abd2c5 | ||
|
|
fb99674217 | ||
|
|
69def38152 | ||
|
|
5759f163e3 | ||
|
|
e3106eaa2a | ||
|
|
edca3bebd7 | ||
|
|
620c68e3f1 | ||
|
|
8f2e382c8a | ||
|
|
6a0ad22774 | ||
|
|
2ac6348fbf | ||
|
|
3086f259ff | ||
|
|
95556d35c8 | ||
|
|
ea4f4c45cb | ||
|
|
808b051a3e | ||
|
|
c55146a78c | ||
|
|
cc5a437573 | ||
|
|
4a53717676 | ||
|
|
8385b88ce8 | ||
|
|
73604e90c8 | ||
|
|
c2d1589e74 | ||
|
|
69973af1ed | ||
|
|
f0c679fb61 | ||
|
|
5a2e2b1773 | ||
|
|
e720b61df6 | ||
|
|
44b121e8b0 | ||
|
|
6a7c086514 | ||
|
|
3b59868f62 | ||
|
|
0b77a3f2c1 | ||
|
|
957dfeed81 | ||
|
|
451c550b19 | ||
|
|
21cc8555b5 | ||
|
|
19b80a1c2d | ||
|
|
a000b1a2fe | ||
|
|
856055a04d | ||
|
|
be1c5f5d1d | ||
|
|
278d46ccd7 | ||
|
|
0da31b6bbb | ||
|
|
e8bc94a25a | ||
|
|
d12869dbac | ||
|
|
fecd70c9ad | ||
|
|
4effa999b3 | ||
|
|
dd35a717b7 | ||
|
|
c71577b7bf | ||
|
|
1d3736b98c | ||
|
|
efad16f2c0 | ||
|
|
243820ca95 | ||
|
|
28805bae65 | ||
|
|
e074643783 | ||
|
|
9340c8aae3 | ||
|
|
9158d79126 | ||
|
|
ded452fdfc | ||
|
|
467e9d1463 | ||
|
|
1429f80cf9 | ||
|
|
372908ba9d | ||
|
|
0d1686e170 | ||
|
|
aa527ba29b | ||
|
|
9a545a48ab | ||
|
|
9e808f3ecd | ||
|
|
cb583b5d6c | ||
|
|
2e3c43ad9e | ||
|
|
594a6c1c0f | ||
|
|
15f81cc316 | ||
|
|
434de44ef5 | ||
|
|
1c1396bf4b | ||
|
|
beea4c4147 | ||
|
|
849f6aa3d9 | ||
|
|
3c4d57f63b | ||
|
|
116caeaa74 | ||
|
|
673d43b526 | ||
|
|
c88053a575 | ||
|
|
1f250e87a3 | ||
|
|
cd89b55f5b | ||
|
|
716d6573ca | ||
|
|
a6b8597f5a | ||
|
|
cab1089e22 | ||
|
|
c95e12c136 | ||
|
|
d9a77d396c | ||
|
|
442f164159 | ||
|
|
d6f9ec3f8f | ||
|
|
9ccfadfb54 | ||
|
|
8b6de30e92 | ||
|
|
6408741733 | ||
|
|
7562e8b172 | ||
|
|
929437c159 | ||
|
|
93474d7f43 | ||
|
|
58e3031510 | ||
|
|
1b66c84303 | ||
|
|
1c321b7de2 | ||
|
|
e3cf364903 | ||
|
|
9b1c09818c | ||
|
|
46ba46ce9d | ||
|
|
1b6035d6c6 | ||
|
|
3e5d6cf88c | ||
|
|
a4c5d0bb62 | ||
|
|
9b316795fc | ||
|
|
b12cd66679 | ||
|
|
aac1a37a3f | ||
|
|
140234aef3 | ||
|
|
ec9715f326 | ||
|
|
69ca14bf46 | ||
|
|
0226f3d047 | ||
|
|
76391edad6 | ||
|
|
9b3822a8bd | ||
|
|
72ec6baf79 | ||
|
|
21769886fc | ||
|
|
2dc1886ee9 | ||
|
|
a29e3789d2 | ||
|
|
17db605b17 | ||
|
|
4e520938c9 | ||
|
|
7498a72f70 | ||
|
|
241bbd80bc | ||
|
|
2e05845410 | ||
|
|
a67263fa27 | ||
|
|
6d8b7bef09 | ||
|
|
3e30f75e7b | ||
|
|
7eb4b40dc7 | ||
|
|
e3a6ac548b | ||
|
|
044e65eb20 | ||
|
|
545604da63 | ||
|
|
4b9aff5b29 | ||
|
|
a93049056a | ||
|
|
3543fa4caa | ||
|
|
51a98736e8 | ||
|
|
12a8cadcfe | ||
|
|
aef959854f |
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
external/** linguist-vendored
|
||||
plugins/libimhex-rust/imgui-rs/** linguist-vendored
|
||||
plugins/libimhex-rust/imgui-sys/** linguist-vendored
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -34,6 +34,10 @@ body:
|
||||
placeholder: X.X.X
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
options:
|
||||
- label: Nightly or built from sources
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context?
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@@ -18,4 +18,4 @@ body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
options:
|
||||
- label: I can provide PoC for that feature or am willing to work on it myself and submit a PR
|
||||
- label: I can provide a PoC for this feature or am willing to work on it myself and submit a PR
|
||||
25
.github/workflows/analysis.yml
vendored
25
.github/workflows/analysis.yml
vendored
@@ -1,16 +1,12 @@
|
||||
name: "CodeQL and Unit Tests"
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '21 0 * * 2'
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: 🐛 Analyze
|
||||
codeql:
|
||||
name: 🐛 CodeQL
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -34,8 +30,8 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
.flatpak-builder
|
||||
key: ${{ runner.os }}-build
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
@@ -44,19 +40,14 @@ jobs:
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
mkdir build
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-10 CXX=g++-10 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-D CMAKE_C_COMPILER_LAUNCHER=ccache -D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
make -j 4 install
|
||||
|
||||
- name: 🧪 Perform Unit Tests
|
||||
run: |
|
||||
cd build
|
||||
ctest
|
||||
|
||||
- name: 🗯️ Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
80
.github/workflows/build.yml
vendored
80
.github/workflows/build.yml
vendored
@@ -19,21 +19,33 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
|
||||
- name: 📜 Restore cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
.flatpak-builder
|
||||
key: ${{ runner.os }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-build-
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf "/usr/local/share/boost"
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
|
||||
sudo apt update
|
||||
sudo bash dist/get_deps_debian.sh
|
||||
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
|
||||
sh rustup-init.sh -y --default-toolchain none
|
||||
rm rustup-init.sh
|
||||
$HOME/.cargo/bin/rustup install nightly
|
||||
$HOME/.cargo/bin/rustup target add x86_64-unknown-linux-gnu
|
||||
$HOME/.cargo/bin/rustup default nightly
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
@@ -42,6 +54,7 @@ jobs:
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$HOME/.cargo/bin/" \
|
||||
..
|
||||
make -j 4 install
|
||||
|
||||
@@ -51,8 +64,18 @@ jobs:
|
||||
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak --user install -y flathub org.freedesktop.Platform//20.08
|
||||
flatpak --user install -y flathub org.freedesktop.Sdk//20.08
|
||||
flatpak-builder --repo=imhex _flatpak dist/net.werwolv.ImHex.yaml --ccache --keep-build-dirs
|
||||
flatpak-builder --jobs=4 --repo=imhex _flatpak dist/net.werwolv.ImHex.yaml --ccache --keep-build-dirs
|
||||
flatpak build-bundle imhex imhex.flatpak net.werwolv.ImHex stable
|
||||
|
||||
- name: 📦 Bundle DEB
|
||||
run: |
|
||||
dpkg-deb --build build/install
|
||||
mv build/install.deb imhex.deb
|
||||
|
||||
- name: 📦 Bundle AppImage
|
||||
run: |
|
||||
dist/AppImage/package.sh build
|
||||
mv build/ImHex-x86_64.AppImage imhex.AppImage
|
||||
|
||||
- name: ⬆️ Upload ELF
|
||||
uses: actions/upload-artifact@v2
|
||||
@@ -66,7 +89,21 @@ jobs:
|
||||
with:
|
||||
name: Linux Flatpak
|
||||
path: |
|
||||
imhex.flatpak
|
||||
imhex.flatpak
|
||||
|
||||
- name: ⬆️ Upload .deb
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Linux DEB
|
||||
path: |
|
||||
imhex.deb
|
||||
|
||||
- name: ⬆️ Upload AppImage
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Linux AppImage
|
||||
path: |
|
||||
imhex.AppImage
|
||||
|
||||
win:
|
||||
runs-on: windows-latest
|
||||
@@ -84,13 +121,30 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
|
||||
- name: 🟦 Install msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: mingw64
|
||||
pacboy: >-
|
||||
gcc:p
|
||||
cmake:p
|
||||
make:p
|
||||
ccache:p
|
||||
glfw:p
|
||||
file:p
|
||||
mbedtls:p
|
||||
python:p
|
||||
freetype:p
|
||||
dlfcn:p
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
bash dist/get_deps_msys2.sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://win.rustup.rs > rustup-init.exe
|
||||
./rustup-init.exe -y --default-host=x86_64-pc-windows-gnu --default-toolchain=none
|
||||
rm rustup-init.exe
|
||||
$USERPROFILE/.cargo/bin/rustup.exe target add x86_64-pc-windows-gnu
|
||||
$USERPROFILE/.cargo/bin/rustup.exe default nightly
|
||||
|
||||
- name: 📜 Prepare Cache
|
||||
id: prep-ccache
|
||||
@@ -104,8 +158,8 @@ jobs:
|
||||
id: cache-ccache
|
||||
with:
|
||||
path: ${{ steps.prep-ccache.outputs.dir }}
|
||||
key: ${{ runner.os }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-build-
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
@@ -121,10 +175,11 @@ jobs:
|
||||
-DCREATE_PACKAGE=ON \
|
||||
-DPython_LIBRARY="$PYTHON_LIB_PATH" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DRUST_PATH="$USERPROFILE/.cargo/bin/" \
|
||||
..
|
||||
mingw32-make -j4 install
|
||||
cpack
|
||||
|
||||
|
||||
- name: ⬆️ Upload Portable ZIP
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
@@ -140,7 +195,6 @@ jobs:
|
||||
build/*.msi
|
||||
|
||||
macos:
|
||||
if: false
|
||||
runs-on: macos-11.0
|
||||
name: 🍎 macOS 11.0
|
||||
steps:
|
||||
@@ -160,8 +214,8 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
key: ${{ runner.os }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-build-
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
|
||||
52
.github/workflows/tests.yml
vendored
Normal file
52
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
name: "Unit Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: 🧪 Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: 🧰 Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: 📜 Restore cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-
|
||||
|
||||
- name: ⬇️ Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo bash dist/get_deps_debian.sh
|
||||
|
||||
- name: 🛠️ Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
CC=gcc-10 CXX=g++-10 cmake \
|
||||
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
..
|
||||
make -j4 unit_tests install
|
||||
|
||||
- name: 🧪 Perform Unit Tests
|
||||
run: |
|
||||
cd build
|
||||
ctest
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,3 +12,6 @@ build*/
|
||||
*.mgc
|
||||
imgui.ini
|
||||
.DS_Store
|
||||
plugins/.rustc_info.json
|
||||
|
||||
**/target
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -18,3 +18,6 @@
|
||||
path = external/curl
|
||||
url = https://github.com/curl/curl
|
||||
ignore = dirty
|
||||
[submodule "external/capstone"]
|
||||
path = external/capstone
|
||||
url = https://github.com/capstone-engine/capstone
|
||||
|
||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/capstone" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/curl" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/fmt" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/nativefiledialog" vcs="Git" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Updating the version here will update it throughout ImHex as well
|
||||
set(IMHEX_VERSION "1.10.1")
|
||||
set(IMHEX_VERSION "1.12.1")
|
||||
project(imhex VERSION ${IMHEX_VERSION})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
@@ -14,11 +14,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set(PLUGINS
|
||||
builtin
|
||||
windows
|
||||
# example
|
||||
# example_cpp
|
||||
# example_rust
|
||||
)
|
||||
|
||||
findLibraries()
|
||||
|
||||
detectOS()
|
||||
detectArch()
|
||||
|
||||
@@ -29,7 +28,7 @@ add_subdirectory(plugins/libimhex)
|
||||
include_directories(include)
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||
|
||||
addVersionDefines()
|
||||
configurePackageCreation()
|
||||
@@ -45,33 +44,7 @@ add_executable(imhex ${application_type}
|
||||
source/init/splash_window.cpp
|
||||
source/init/tasks.cpp
|
||||
|
||||
source/helpers/patches.cpp
|
||||
source/helpers/project_file_handler.cpp
|
||||
source/helpers/loader_script_handler.cpp
|
||||
source/helpers/plugin_manager.cpp
|
||||
source/helpers/encoding_file.cpp
|
||||
|
||||
source/providers/file_provider.cpp
|
||||
|
||||
source/views/view_hexeditor.cpp
|
||||
source/views/view_pattern_editor.cpp
|
||||
source/views/view_pattern_data.cpp
|
||||
source/views/view_hashes.cpp
|
||||
source/views/view_information.cpp
|
||||
source/views/view_help.cpp
|
||||
source/views/view_tools.cpp
|
||||
source/views/view_strings.cpp
|
||||
source/views/view_data_inspector.cpp
|
||||
source/views/view_disassembler.cpp
|
||||
source/views/view_bookmarks.cpp
|
||||
source/views/view_patches.cpp
|
||||
source/views/view_command_palette.cpp
|
||||
source/views/view_settings.cpp
|
||||
source/views/view_data_processor.cpp
|
||||
source/views/view_yara.cpp
|
||||
source/views/view_constants.cpp
|
||||
source/views/view_store.cpp
|
||||
source/views/view_diff.cpp
|
||||
|
||||
${imhex_icon}
|
||||
)
|
||||
@@ -79,9 +52,9 @@ add_executable(imhex ${application_type}
|
||||
set_target_properties(imhex PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(imhex dl libimhex wsock32 ws2_32 Dwmapi.lib)
|
||||
target_link_libraries(imhex PUBLIC dl libimhex wsock32 ws2_32 Dwmapi.lib)
|
||||
else ()
|
||||
target_link_libraries(imhex dl libimhex pthread)
|
||||
target_link_libraries(imhex PUBLIC dl libimhex pthread)
|
||||
endif ()
|
||||
|
||||
createPackage()
|
||||
|
||||
68
README.md
68
README.md
@@ -4,7 +4,8 @@
|
||||
|
||||
<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/workflow/status/WerWolv/ImHex/Build?longCache=true&style=for-the-badge&label=Build&logoColor=fff&logo=GitHub%20Actions"></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&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&style=for-the-badge"></a>
|
||||
<a title="Total Downloads" href="https://github.com/WerWolv/ImHex/releases/latest"><img alt="Total Downloads" src="https://img.shields.io/github/downloads/WerWolv/ImHex/total?longCache=true&style=for-the-badge&label=Downloads&logoColor=fff&logo=GitHub"></a>
|
||||
</p>
|
||||
|
||||
## Supporting
|
||||
@@ -17,6 +18,11 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
<a href="https://werwolv.net/donate"><img src="https://werwolv.net/assets/paypal_banner.png" alt="PayPal donate button" /> </a>
|
||||
</p>
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||
|
||||
## Features
|
||||
|
||||
- Featureful hex view
|
||||
@@ -33,7 +39,7 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
- Goto from start, end and current cursor position
|
||||
- Custom C++-like pattern language for parsing highlighting a file's content
|
||||
- Automatic loading based on MIME type
|
||||
- arrays, pointers, structs, unions, enums, bitfields, using declarations, little and big endian support, conditionals and much more!
|
||||
- arrays, pointers, structs, unions, enums, bitfields, namespaces, little and big endian support, conditionals and much more!
|
||||
- Useful error messages, syntax highlighting and error marking
|
||||
- Data importing
|
||||
- Base64 files
|
||||
@@ -71,23 +77,36 @@ If you like my work, please consider supporting me on GitHub Sponsors, Patreon o
|
||||
- Entropy graph
|
||||
- Highest and average entropy
|
||||
- Encrypted / Compressed file detection
|
||||
- Built-in Content Store
|
||||
- Download all files found in the database directly from within ImHex
|
||||
- Yara Rules support
|
||||
- Quickly scan a file for vulnearabilities with official yara rules
|
||||
- Helpful tools
|
||||
- Itanium and MSVC demangler
|
||||
- ASCII table
|
||||
- Regex replacer
|
||||
- Mathematical expression evaluator (Calculator)
|
||||
- Hexadecimal Color picker
|
||||
- Base converter
|
||||
- UNIX Permissions calculator
|
||||
- Anonfiles File upload tool
|
||||
- Wikipedia term definition finder
|
||||
- File utilities
|
||||
- File splitter
|
||||
- File combiner
|
||||
- File shredderer
|
||||
- Built-in cheat sheet for pattern language and Math evaluator
|
||||
- Doesn't burn out your retinas when used in late-night sessions
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||
|
||||
## Pattern Language
|
||||
|
||||
The custom C-like Pattern Language developed and used by ImHex is easy to read, understand and learn. A guide with all features of the language can be found [in the wiki](https://github.com/WerWolv/ImHex/wiki/Pattern-Language-Guide) or a simpler version in ImHex under `Help -> Pattern Language Cheat Sheet`
|
||||
The custom C-like Pattern Language developed and used by ImHex is easy to read, understand and learn. A guide with all features of the language can be found [on the docs page](http://imhex.werwolv.net/docs).
|
||||
|
||||
## Plugin development
|
||||
|
||||
To develop plugins for ImHex, use one of the following two templates projects to get startet. You then have access to the entirety of libimhex as well as the ImHex API and the Content Registry to interact with ImHex or to add new content.
|
||||
- [C++ Plugin Template](https://github.com/WerWolv/ImHex-Cpp-Plugin-Template)
|
||||
- [Rust Plugin Template](https://github.com/WerWolv/ImHex-Rust-Plugin-Template)
|
||||
|
||||
## Additional Files
|
||||
|
||||
@@ -98,25 +117,22 @@ For format patterns, includable libraries and magic files, check out the [ImHex-
|
||||
Nightlies are available via GitHub Actions [here](https://github.com/WerWolv/ImHex/actions?query=workflow%3ABuild).
|
||||
|
||||
- Windows • __x86_64__
|
||||
- [MSI Installer](https://nightly.link/WerWolv/ImHex/workflows/build/master/Windows%20Installer.zip)
|
||||
- [Portable ZIP](https://nightly.link/WerWolv/ImHex/workflows/build/master/Windows%20Portable%20ZIP.zip)
|
||||
- [MSI](https://nightly.link/WerWolv/ImHex/workflows/build/master/Windows%20Installer.zip)
|
||||
- [EXE](https://nightly.link/WerWolv/ImHex/workflows/build/master/Windows%20Portable%20ZIP.zip)
|
||||
- MacOS • __x86_64__
|
||||
- [DMG](https://nightly.link/WerWolv/ImHex/workflows/build/master/macOS%20DMG.zip)
|
||||
- Linux • __x86_64__
|
||||
- [ELF](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20ELF.zip)
|
||||
- [Flatpak](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20Flatpak.zip)
|
||||
|
||||
## Compiling
|
||||
|
||||
You need a C++20 compatible compiler such as GCC 10.2.0 to compile ImHex. Moreover, the following dependencies are needed for compiling ImHex:
|
||||
You need a C++20 compatible compiler such as GCC 10.2.0 to compile ImHex.
|
||||
|
||||
- GLFW3
|
||||
- libmagic, libgnurx, libtre, libintl, libiconv
|
||||
- libmbedtls
|
||||
- capstone
|
||||
- Python3
|
||||
- freetype2
|
||||
- Brew (macOS only)
|
||||
- Xcode (macOS only)
|
||||
Many dependencies are bundled into the repository using submodules so make sure to clone it using the `--recurse-submodules` option.
|
||||
All dependencies that aren't bundled, can be installed using the dependency installer scripts found in the `/dist` folder.
|
||||
|
||||
For working examples
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -199,9 +215,19 @@ with the environment variables `XDG_CONFIG_HOME`, `XDG_CONFIG_DIRS`,
|
||||
|
||||
## Credits
|
||||
|
||||
### Contributors
|
||||
|
||||
- [Mary](https://github.com/Thog) for her immense help porting ImHex to MacOS and help during development
|
||||
- [Roblabla](https://github.com/Roblabla) for adding MSI Installer support to ImHex
|
||||
- [jam1garner](https://github.com/jam1garner) and [raytwo](https://github.com/raytwo) for their help with adding Rust support to plugins
|
||||
- All other people that have been reporting issues on Discord or GitHub that I had great conversations with :)
|
||||
|
||||
### Libraries
|
||||
|
||||
- Thanks a lot to ocornut for their amazing [Dear ImGui](https://github.com/ocornut/imgui) which is used for building the entire interface
|
||||
- Thanks to orconut as well for their hex editor view used as base for this project.
|
||||
- Thanks to ocornut as well for their hex editor view used as base for this project.
|
||||
- Thanks to BalazsJako for their incredible [ImGuiColorTextEdit](https://github.com/BalazsJako/ImGuiColorTextEdit) used for the pattern language syntax highlighting
|
||||
- Thanks to AirGuanZ for their amazing [imgui-filebrowser](https://github.com/AirGuanZ/imgui-filebrowser) used for loading and saving files
|
||||
- Thanks to nlohmann for their [json](https://github.com/nlohmann/json) library used for project files
|
||||
- Thanks to aquynh for [capstone](https://github.com/aquynh/capstone) which is the base of the disassembly window
|
||||
- Thanks to vitaut for their [libfmt](https://github.com/fmtlib/fmt) library which makes formatting and logging so much better
|
||||
- Thanks to rxi for [microtar](https://github.com/rxi/microtar) used for extracting downloaded store assets
|
||||
|
||||
@@ -27,22 +27,13 @@ macro(addVersionDefines)
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DRELEASE -DIMHEX_VERSION=\"\\\"${PROJECT_VERSION}-ReleaseMinimumSize\"\\\"")
|
||||
endmacro()
|
||||
|
||||
macro(findLibraries)
|
||||
macro(configurePython)
|
||||
set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
|
||||
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
|
||||
|
||||
# Enforce that we use non system Python 3 on macOS.
|
||||
set(Python_FIND_FRAMEWORK NEVER)
|
||||
|
||||
# Find packages
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
find_package(mbedTLS 2.26.0 REQUIRED)
|
||||
|
||||
pkg_search_module(CAPSTONE 4.0.2 REQUIRED capstone)
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
find_package(Python COMPONENTS Development REQUIRED)
|
||||
if(Python_VERSION LESS 3)
|
||||
message(STATUS ${PYTHON_VERSION_MAJOR_MINOR})
|
||||
@@ -59,13 +50,6 @@ macro(findLibraries)
|
||||
list(JOIN PYTHON_VERSION_MAJOR_MINOR "." PYTHON_VERSION_MAJOR_MINOR)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -DPYTHON_VERSION_MAJOR_MINOR=\"\\\"${PYTHON_VERSION_MAJOR_MINOR}\"\\\"")
|
||||
|
||||
pkg_search_module(MAGIC libmagic>=5.39)
|
||||
if(NOT MAGIC_FOUND)
|
||||
find_library(MAGIC 5.39 magic REQUIRED)
|
||||
else()
|
||||
set(MAGIC_INCLUDE_DIRS ${MAGIC_INCLUDEDIR})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Detect current OS / System
|
||||
@@ -84,10 +68,10 @@ macro(detectOS)
|
||||
set(MAGIC_INSTALL_LOCATION "magic")
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_LINUX")
|
||||
set(CMAKE_INSTALL_BINDIR "bin")
|
||||
set(CMAKE_INSTALL_LIBDIR "lib")
|
||||
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "share/imhex/magic")
|
||||
set(CMAKE_INSTALL_BINDIR "usr/bin")
|
||||
set(CMAKE_INSTALL_LIBDIR "usr/lib")
|
||||
set(PLUGINS_INSTALL_LOCATION "usr/share/imhex/plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "usr/share/imhex/magic")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||
endif()
|
||||
@@ -114,7 +98,7 @@ macro(configurePackageCreation)
|
||||
set(application_type)
|
||||
set(imhex_icon "${CMAKE_SOURCE_DIR}/res/resource.rc")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--allow-multiple-definition")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wl,-subsystem,windows")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-subsystem,windows")
|
||||
|
||||
if (CREATE_PACKAGE)
|
||||
set(CPACK_GENERATOR "WIX")
|
||||
@@ -157,18 +141,37 @@ macro(createPackage)
|
||||
add_subdirectory("plugins/${plugin}")
|
||||
if (TARGET ${plugin})
|
||||
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
if (WIN32)
|
||||
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})
|
||||
set_target_properties(${plugin} PROPERTIES CARGO_BUILD_TARGET_DIR ${CMAKE_BINARY_DIR}/plugins)
|
||||
|
||||
get_target_property(IS_RUST_PROJECT ${plugin} RUST_PROJECT)
|
||||
|
||||
if (IS_RUST_PROJECT)
|
||||
set_target_properties(${plugin} PROPERTIES CARGO_BUILD_TARGET_DIR ${CMAKE_BINARY_DIR}/plugins)
|
||||
|
||||
get_target_property(PLUGIN_LOCATION ${plugin} LOCATION)
|
||||
|
||||
install(FILES "${PLUGIN_LOCATION}/../${plugin}.hexplug" DESTINATION "${PLUGINS_INSTALL_LOCATION}")
|
||||
else ()
|
||||
install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION})
|
||||
set_target_properties(${plugin} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
if (WIN32)
|
||||
install(TARGETS ${plugin} RUNTIME DESTINATION ${PLUGINS_INSTALL_LOCATION})
|
||||
elseif (APPLE)
|
||||
if (CREATE_BUNDLE)
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:imhex>/${PLUGINS_INSTALL_LOCATION})
|
||||
else ()
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins)
|
||||
endif ()
|
||||
else ()
|
||||
install(TARGETS ${plugin} LIBRARY DESTINATION ${PLUGINS_INSTALL_LOCATION})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
add_dependencies(imhex ${plugin})
|
||||
endif ()
|
||||
endforeach()
|
||||
|
||||
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
set_target_properties(libimhex PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
install(TARGETS libimhex RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
if (WIN32)
|
||||
# Install binaries directly in the prefix, usually C:\Program Files\ImHex.
|
||||
@@ -180,19 +183,19 @@ macro(createPackage)
|
||||
INSTALL(CODE "LIST(APPEND DEP_FOLDERS \${PY_PARENT})")
|
||||
install(CODE [[
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
EXECUTABLES $<TARGET_FILE:imhex>
|
||||
EXECUTABLES $<TARGET_FILE:builtin> $<TARGET_FILE:libimhex> $<TARGET_FILE:imhex>
|
||||
RESOLVED_DEPENDENCIES_VAR _r_deps
|
||||
UNRESOLVED_DEPENDENCIES_VAR _u_deps
|
||||
CONFLICTING_DEPENDENCIES_PREFIX _c_deps
|
||||
DIRECTORIES ${DEP_FOLDERS}
|
||||
DIRECTORIES ${DEP_FOLDERS} $ENV{PATH}
|
||||
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
|
||||
)
|
||||
|
||||
if(_u_deps)
|
||||
message(WARNING "There were unresolved dependencies for binary $<TARGET_FILE:imhex>: \"${_u_deps}\"!")
|
||||
message(WARNING "There were unresolved dependencies for binary: \"${_u_deps}\"!")
|
||||
endif()
|
||||
if(_c_deps_FILENAMES)
|
||||
message(WARNING "There were conflicting dependencies for library $<TARGET_FILE:imhex>: \"${_c_deps}\"!")
|
||||
message(WARNING "There were conflicting dependencies for library: \"${_c_deps}\"!")
|
||||
endif()
|
||||
|
||||
foreach(_file ${_r_deps})
|
||||
@@ -204,6 +207,11 @@ macro(createPackage)
|
||||
)
|
||||
endforeach()
|
||||
]])
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/DEBIAN/control DESTINATION ${CMAKE_INSTALL_PREFIX}/DEBIAN)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/share/applications)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/res/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/share/pixmaps RENAME imhex.png)
|
||||
endif()
|
||||
|
||||
if (CREATE_BUNDLE)
|
||||
|
||||
@@ -26,9 +26,8 @@ get_filename_component(BUNDLE_PATH "${BUNDLE_PATH}" ABSOLUTE)
|
||||
message(STATUS "Fixing up application bundle: ${BUNDLE_PATH}")
|
||||
|
||||
|
||||
# Make sure to fix up any additional shared libraries (like plugins) that are
|
||||
# needed.
|
||||
file(GLOB_RECURSE extra_libs "${BUNDLE_PATH}/Contents/MacOS/*.dylib")
|
||||
# Make sure to fix up any included ImHex plugin.
|
||||
file(GLOB_RECURSE extra_libs "${BUNDLE_PATH}/Contents/MacOS/plugins/*.hexplug")
|
||||
|
||||
message(STATUS "Fixing up application bundle: ${extra_dirs}")
|
||||
|
||||
|
||||
40
dist/AppImage/Dockerfile
vendored
Normal file
40
dist/AppImage/Dockerfile
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
FROM debian:bullseye-slim
|
||||
LABEL maintainer Example <example@example.com>
|
||||
|
||||
ARG TAG=master
|
||||
ARG REPO=https://github.com/WerWolv/ImHex.git
|
||||
|
||||
USER root
|
||||
|
||||
# Bring packages up to date
|
||||
RUN apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get autoremove -y \
|
||||
&& apt-get install -y \
|
||||
git \
|
||||
cmake \
|
||||
curl \
|
||||
squashfs-tools
|
||||
|
||||
# Fetch source and dependencies
|
||||
RUN mkdir -p /source \
|
||||
&& cd /source \
|
||||
&& git clone $REPO \
|
||||
&& cd ImHex \
|
||||
&& git checkout $TAG \
|
||||
&& git submodule update --init --recursive \
|
||||
&& cd /source/ImHex/dist \
|
||||
&& ./get_deps_debian.sh
|
||||
|
||||
ARG CXX=g++-10
|
||||
|
||||
# Build ImHex
|
||||
RUN mkdir -p /source/ImHex/build \
|
||||
&& cd /source/ImHex/build \
|
||||
&& cmake --install-prefix /usr -DCMAKE_BUILD_TYPE=Release .. \
|
||||
&& make -j
|
||||
|
||||
# Prepare for AppImage
|
||||
RUN cd /source/ImHex/dist/AppImage \
|
||||
&& ./package.sh /source/ImHex/build \
|
||||
&& mv /source/ImHex/build/ImHex-x86_64.AppImage /
|
||||
6
dist/AppImage/ImHex.desktop
vendored
Normal file
6
dist/AppImage/ImHex.desktop
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name=ImHex
|
||||
Exec=imhex
|
||||
Icon=imhex
|
||||
Type=Application
|
||||
Categories=Utility;
|
||||
22
dist/AppImage/README.md
vendored
Normal file
22
dist/AppImage/README.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Building an AppImage
|
||||
There are two ways of building an AppImage for ImHex, using the provided
|
||||
tools here.
|
||||
|
||||
If you want to create an AppImage and do not have a build to work from
|
||||
already, you can use docker to build ImHex and package an AppImage.
|
||||
|
||||
Alternatively you can create an AppImage using an existing build.
|
||||
|
||||
## Using docker
|
||||
First run `build.sh` to create a docker image. Then run `extract.sh` to get the
|
||||
AppImage out. This needs to be in two steps, as a docker build cannot copy
|
||||
files out. Nor can docker build use volume mounts.
|
||||
|
||||
The environment variable TAG can be set to build for a specific git tag.
|
||||
Without the master branch is build.
|
||||
|
||||
## Using an existing build
|
||||
Run `package.sh` with the build dir as an argument. E.g.:
|
||||
```
|
||||
./package.sh ../../build
|
||||
```
|
||||
16
dist/AppImage/build.sh
vendored
Executable file
16
dist/AppImage/build.sh
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set the TAG environment variable to build a specific tag
|
||||
# Set the REPO environment variable to point at a different git repository
|
||||
|
||||
# Make sure we're in the same directory as this script
|
||||
pushd $(dirname "$(realpath "$0")")
|
||||
|
||||
BUILDARG=""
|
||||
SUFFIX=""
|
||||
[ -n "${TAG}" ] && BUILDARG="${BUILDARG} --build-arg=TAG=${TAG}" && SUFFIX=":${TAG}"
|
||||
[ -n "${REPO}" ] && BUILDARG="${BUILDARG} --build-arg=REPO=${REPO}"
|
||||
|
||||
docker build ${BUILDARG} -t imhex-appimage-build${SUFFIX} .
|
||||
|
||||
popd
|
||||
26
dist/AppImage/extract.sh
vendored
Executable file
26
dist/AppImage/extract.sh
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set the TAG environment variable to move to a versioned name while extracting
|
||||
|
||||
# Make sure we're in the same directory as this script
|
||||
pushd $(dirname "$(realpath "$0")")
|
||||
|
||||
SUFFIX=""
|
||||
[ -n "$TAG" ] && SUFFIX=":$TAG"
|
||||
|
||||
# Remove old containers
|
||||
docker rm imhex 2>&1 > /dev/null
|
||||
|
||||
docker run -d --name imhex imhex-appimage-build${SUFFIX} sleep 30 &
|
||||
sleep 15
|
||||
docker cp imhex:/ImHex-x86_64.AppImage .
|
||||
|
||||
# Move to tagged name if $TAG set
|
||||
if [ -n "$TAG" ]; then
|
||||
mv ImHex-x86_64.AppImage ImHex-${TAG}-x86_64.AppImage
|
||||
echo -e "\nThe created AppImage can be found here:\n $(pwd)/ImHex-${TAG}-x86_64.AppImage\n\n"
|
||||
else
|
||||
echo -e "\nThe created AppImage can be found here:\n $(pwd)/ImHex-x86_64.AppImage\n\n"
|
||||
fi
|
||||
|
||||
popd
|
||||
BIN
dist/AppImage/imhex.png
vendored
Normal file
BIN
dist/AppImage/imhex.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
58
dist/AppImage/package.sh
vendored
Executable file
58
dist/AppImage/package.sh
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
set -e # Exit on error
|
||||
set -o pipefail # Bash specific
|
||||
|
||||
usage() {
|
||||
echo "Tool to package an ImHex build into an AppImage"
|
||||
echo
|
||||
echo "Usage:"
|
||||
echo "$0 <build dir>"
|
||||
echo
|
||||
exit
|
||||
}
|
||||
|
||||
MYDIR=$(dirname "$(realpath "$0")")
|
||||
|
||||
# Check is a build dir has been specified and it's a dir
|
||||
[ -z "$1" ] && usage
|
||||
[ -d "$1" ] || usage
|
||||
|
||||
set -u # Throw errors when unset variables are used
|
||||
|
||||
BUILDDIR=$1
|
||||
APPDIR=${BUILDDIR}/ImHex.AppDir
|
||||
APPIMAGE=${BUILDDIR}/ImHex-x86_64.AppImage
|
||||
|
||||
# Prepare for AppImage
|
||||
## Fetch the needed AppImage binaries
|
||||
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/AppRun-x86_64 -o ${MYDIR}/AppRun-x86_64
|
||||
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/runtime-x86_64 -o ${MYDIR}/runtime-x86_64
|
||||
|
||||
## Setup directory structure
|
||||
mkdir -p ${BUILDDIR}/ImHex.AppDir/usr/{bin,lib} ${BUILDDIR}/ImHex.AppDir/usr/share/imhex/plugins
|
||||
|
||||
## Add ImHex files to structure
|
||||
cp ${BUILDDIR}/imhex ${APPDIR}/usr/bin
|
||||
cp ${BUILDDIR}/plugins/builtin/builtin.hexplug ${APPDIR}/usr/share/imhex/plugins
|
||||
cp ${MYDIR}/{AppRun-x86_64,ImHex.desktop,imhex.png} ${APPDIR}/
|
||||
mv ${BUILDDIR}/ImHex.AppDir/AppRun-x86_64 ${APPDIR}/AppRun
|
||||
chmod a+x ${BUILDDIR}/ImHex.AppDir/AppRun
|
||||
|
||||
## Add all dependencies
|
||||
ldd ${BUILDDIR}/imhex | awk '/ => /{print $3}' | awk '!/(libc|libstdc++|libc++|libdl|libpthread|libselinux|ld-linux|libgdk)/' | xargs -I '{}' cp '{}' ${APPDIR}/usr/lib
|
||||
ldd ${BUILDDIR}/plugins/builtin/builtin.hexplug | awk '/ => /{print $3}' | awk '!/(libc|libstdc++|libc++|libdl|libpthread|libselinux|ld-linux|libgdk)/' | xargs -I '{}' cp '{}' ${APPDIR}/usr/lib
|
||||
ldd ${BUILDDIR}/plugins/libimhex/libimhex.so | awk '/ => /{print $3}' | awk '!/(libc|libstdc++|libc++|libdl|libpthread|libselinux|ld-linux|libgdk)/' | xargs -I '{}' cp '{}' ${APPDIR}/usr/lib
|
||||
|
||||
# Package it up as described here:
|
||||
# https://github.com/AppImage/AppImageKit#appimagetool-usage
|
||||
# under 'If you want to generate an AppImage manually'
|
||||
# This builds a v2 AppImage according to
|
||||
# https://github.com/AppImage/AppImageSpec/blob/master/draft.md#type-2-image-format
|
||||
mksquashfs ${APPDIR} ${BUILDDIR}/ImHex.squashfs -root-owned -noappend
|
||||
cat ${MYDIR}/runtime-x86_64 > ${APPIMAGE}
|
||||
cat ${BUILDDIR}/ImHex.squashfs >> ${APPIMAGE}
|
||||
chmod a+x ${APPIMAGE}
|
||||
|
||||
if [ ! -f /.dockerenv ]; then
|
||||
echo -e "\nThe created AppImage can be found here:\n ${APPIMAGE}\n\n"
|
||||
fi
|
||||
1
dist/Brewfile
vendored
1
dist/Brewfile
vendored
@@ -1,6 +1,5 @@
|
||||
brew "glfw3"
|
||||
brew "mbedtls"
|
||||
brew "capstone"
|
||||
brew "nlohmann-json"
|
||||
brew "cmake"
|
||||
brew "ccache"
|
||||
|
||||
12
dist/DEBIAN/control.in
vendored
Normal file
12
dist/DEBIAN/control.in
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Package: ImHex
|
||||
Version: ${PROJECT_VERSION}
|
||||
Section: editors
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
License: GNU GPL-2
|
||||
Depends: libglfw3-dev, libmagic-dev, libmbedtls-dev, libcapstone-dev, python3-dev, libfreetype-dev, libgtk-3-dev, libldap2-dev
|
||||
Maintainer: WerWolv <hey@werwolv.net>
|
||||
Description: ImHex Hex Editor
|
||||
A Hex Editor for Reverse Engineers, Programmers and
|
||||
people who value their retinas when working at 3 AM.
|
||||
|
||||
11
dist/DEBIAN/imhex.desktop
vendored
Normal file
11
dist/DEBIAN/imhex.desktop
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Name=ImHex
|
||||
Comment=ImHex Hex Editor
|
||||
GenericName=Hex Editor
|
||||
Exec=/usr/bin/imhex %U
|
||||
Icon=/usr/share/pixmaps/imhex.png
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GNOME;GTK;Development;
|
||||
StartupWMClass=imhex
|
||||
|
||||
1
dist/Dockerfile
vendored
1
dist/Dockerfile
vendored
@@ -13,7 +13,6 @@ RUN pacman -S --needed --noconfirm \
|
||||
glfw-x11 \
|
||||
file \
|
||||
mbedtls \
|
||||
capstone \
|
||||
python3 \
|
||||
freetype2 \
|
||||
gtk3
|
||||
|
||||
1
dist/ImHex-9999.ebuild
vendored
1
dist/ImHex-9999.ebuild
vendored
@@ -26,7 +26,6 @@ RDEPEND="${DEPEND}
|
||||
media-libs/glfw
|
||||
sys-apps/file
|
||||
dev-libs/mbedtls
|
||||
dev-libs/capstone
|
||||
dev-cpp/nlohmann_json
|
||||
x11-libs/gtk+
|
||||
"
|
||||
|
||||
1
dist/get_deps_archlinux.sh
vendored
1
dist/get_deps_archlinux.sh
vendored
@@ -6,7 +6,6 @@ pacman -S --needed \
|
||||
glfw \
|
||||
file \
|
||||
mbedtls \
|
||||
capstone \
|
||||
python3 \
|
||||
freetype2 \
|
||||
gtk3
|
||||
|
||||
1
dist/get_deps_debian.sh
vendored
1
dist/get_deps_debian.sh
vendored
@@ -22,7 +22,6 @@ apt install -y \
|
||||
libglm-dev \
|
||||
libmagic-dev \
|
||||
libmbedtls-dev \
|
||||
libcapstone-dev \
|
||||
python3-dev \
|
||||
libfreetype-dev \
|
||||
libgtk-3-dev \
|
||||
|
||||
3
dist/get_deps_fedora.sh
vendored
3
dist/get_deps_fedora.sh
vendored
@@ -3,11 +3,10 @@
|
||||
dnf install \
|
||||
cmake \
|
||||
gcc-c++ \
|
||||
capstone-devel \
|
||||
file-devel \
|
||||
glfw-devel \
|
||||
mesa-libGL-devel \
|
||||
mbedtls-devel \
|
||||
python-devel \
|
||||
freetype-devel \
|
||||
gtk3
|
||||
gtk3-devel
|
||||
|
||||
1
dist/get_deps_msys2.sh
vendored
1
dist/get_deps_msys2.sh
vendored
@@ -5,7 +5,6 @@ pacman -S --needed --noconfirm \
|
||||
mingw-w64-x86_64-cmake \
|
||||
mingw-w64-x86_64-make \
|
||||
mingw-w64-x86_64-ccache \
|
||||
mingw-w64-x86_64-capstone \
|
||||
mingw-w64-x86_64-glfw \
|
||||
mingw-w64-x86_64-file \
|
||||
mingw-w64-x86_64-mbedtls \
|
||||
|
||||
11
dist/imhex.desktop
vendored
Normal file
11
dist/imhex.desktop
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Name=ImHex
|
||||
Comment=ImHex Hex Editor
|
||||
GenericName=Hex Editor
|
||||
Exec=/usr/bin/imhex %U
|
||||
Icon=/usr/share/pixmaps/imhex.png
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GNOME;GTK;Development;
|
||||
StartupWMClass=imhex
|
||||
|
||||
1
dist/msys2/PKGBUILD
vendored
1
dist/msys2/PKGBUILD
vendored
@@ -12,7 +12,6 @@ makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
|
||||
"${MINGW_PACKAGE_PREFIX}-cmake"
|
||||
"${MINGW_PACKAGE_PREFIX}-make"
|
||||
"${MINGW_PACKAGE_PREFIX}-dlfcn"
|
||||
"${MINGW_PACKAGE_PREFIX}-capstone"
|
||||
"${MINGW_PACKAGE_PREFIX}-glfw"
|
||||
"${MINGW_PACKAGE_PREFIX}-file"
|
||||
"${MINGW_PACKAGE_PREFIX}-mbedtls"
|
||||
|
||||
16
dist/net.werwolv.ImHex.yaml
vendored
16
dist/net.werwolv.ImHex.yaml
vendored
@@ -3,7 +3,7 @@ runtime: org.freedesktop.Platform
|
||||
runtime-version: '20.08'
|
||||
default-branch: stable
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: imhex
|
||||
command: /bin/imhex
|
||||
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
@@ -12,16 +12,6 @@ finish-args:
|
||||
- --device=all
|
||||
|
||||
modules:
|
||||
- name: capstone
|
||||
buildsystem: cmake-ninja
|
||||
builddir: true
|
||||
config-opts:
|
||||
- -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
sources:
|
||||
- type: archive
|
||||
url: https://github.com/aquynh/capstone/archive/4.0.2.tar.gz
|
||||
sha256: 7c81d798022f81e7507f1a60d6817f63aa76e489aa4e7055255f21a22f5e526a
|
||||
|
||||
- name: libiconv
|
||||
sources:
|
||||
- type: archive
|
||||
@@ -64,8 +54,8 @@ modules:
|
||||
sha256: 4cf0df69731494668bdd6460ed8cb269b68de9c19ad8c27abc24cd72605b2d5b
|
||||
|
||||
- name: imhex
|
||||
buildsystem: cmake-ninja
|
||||
buildsystem: cmake
|
||||
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/WerWolv/ImHex.git
|
||||
url: https://github.com/WerWolv/ImHex.git
|
||||
|
||||
15
external/ImGui/CMakeLists.txt
vendored
15
external/ImGui/CMakeLists.txt
vendored
@@ -5,11 +5,16 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_search_module(GLFW REQUIRED glfw3)
|
||||
|
||||
if (UNIX)
|
||||
find_package(OpenGL REQUIRED)
|
||||
endif ()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
|
||||
add_library(imgui STATIC
|
||||
add_library(imgui OBJECT
|
||||
source/imgui.cpp
|
||||
source/imgui_demo.cpp
|
||||
source/imgui_draw.cpp
|
||||
@@ -19,6 +24,8 @@ add_library(imgui STATIC
|
||||
source/imgui_tables.cpp
|
||||
source/imgui_widgets.cpp
|
||||
|
||||
source/cimgui.cpp
|
||||
|
||||
source/TextEditor.cpp
|
||||
|
||||
source/imgui_imhex_extensions.cpp
|
||||
@@ -36,12 +43,12 @@ add_library(imgui STATIC
|
||||
|
||||
add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD)
|
||||
|
||||
target_include_directories(imgui PUBLIC include fonts ${FREETYPE_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS})
|
||||
target_include_directories(imgui PUBLIC include fonts ${CMAKE_CURRENT_SOURCE_DIR} ${FREETYPE_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS})
|
||||
|
||||
target_link_directories(imgui PUBLIC ${GLFW_LIBRARY_DIRS})
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(imgui Freetype::Freetype glfw3 opengl32.lib)
|
||||
target_link_libraries(imgui PUBLIC Freetype::Freetype glfw3 opengl32.lib)
|
||||
elseif (UNIX)
|
||||
target_link_libraries(imgui Freetype::Freetype glfw GL)
|
||||
target_link_libraries(imgui PUBLIC Freetype::Freetype glfw OpenGL::GL)
|
||||
endif()
|
||||
|
||||
3485
external/ImGui/include/cimgui.h
vendored
Normal file
3485
external/ImGui/include/cimgui.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,8 @@ namespace ImGui {
|
||||
}
|
||||
};
|
||||
|
||||
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data);
|
||||
|
||||
bool IconHyperlink(const char *icon, const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool Hyperlink(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
bool BulletHyperlink(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
|
||||
@@ -61,7 +63,8 @@ namespace ImGui {
|
||||
void InfoTooltip(const char *text);
|
||||
|
||||
bool TitleBarButton(const char* label, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color, ImVec2 size_arg);
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color);
|
||||
bool IconButton(const char* symbol, ImVec4 color, ImVec2 size_arg = ImVec2(0, 0));
|
||||
|
||||
inline bool HasSecondPassed() {
|
||||
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
|
||||
|
||||
@@ -149,6 +149,7 @@ typedef khronos_uint8_t GLubyte;
|
||||
#define GL_FILL 0x1B02
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
|
||||
31
external/ImGui/include/imgui_memory_editor.h
vendored
31
external/ImGui/include/imgui_memory_editor.h
vendored
@@ -239,7 +239,9 @@ struct MemoryEditor
|
||||
DataPreviewAddrOld = DataPreviewAddr;
|
||||
DataPreviewAddrEndOld = DataPreviewAddrEnd;
|
||||
|
||||
DrawContents(mem_data, mem_size, base_display_addr);
|
||||
if (mem_size > 0)
|
||||
DrawContents(mem_data, mem_size, base_display_addr);
|
||||
|
||||
if (ContentsWidthChanged)
|
||||
{
|
||||
CalcSizes(s, mem_size, base_display_addr);
|
||||
@@ -393,8 +395,8 @@ struct MemoryEditor
|
||||
bool is_highlight_from_preview = (addr >= DataPreviewAddr && addr <= DataPreviewAddrEnd) || (addr >= DataPreviewAddrEnd && addr <= DataPreviewAddr);
|
||||
if (is_highlight_from_user_range || is_highlight_from_user_func || is_highlight_from_preview)
|
||||
{
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
float highlight_width = s.GlyphWidth * 2;
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos() - ImVec2(ImGui::GetStyle().CellPadding.x / 2, 0);
|
||||
float highlight_width = s.GlyphWidth * 2 + ImGui::GetStyle().CellPadding.x / 2;
|
||||
bool is_next_byte_highlighted = (addr + 1 < mem_size) &&
|
||||
((HighlightMax != (size_t)-1 && addr + 1 < HighlightMax) ||
|
||||
(HighlightFn && HighlightFn(mem_data, addr + 1, true)) ||
|
||||
@@ -411,6 +413,23 @@ struct MemoryEditor
|
||||
color = (ImAlphaBlendColors(HighlightColor, 0x60C08080) & 0x00FFFFFF) | 0x90000000;
|
||||
|
||||
draw_list->AddRectFilled(pos, ImVec2(pos.x + highlight_width, pos.y + s.LineHeight), color);
|
||||
|
||||
if (is_highlight_from_preview) {
|
||||
size_t min = std::min(DataPreviewAddr, DataPreviewAddrEnd);
|
||||
size_t max = std::max(DataPreviewAddr, DataPreviewAddrEnd);
|
||||
|
||||
if (n == 0 || addr == min)
|
||||
draw_list->AddLine(pos, pos + ImVec2(0, s.LineHeight), ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Text)), 1.0F);
|
||||
if (n == Cols - 1 || addr == max) {
|
||||
draw_list->AddRectFilled(pos + ImVec2(highlight_width, 0), pos + ImVec2(highlight_width + 1, s.LineHeight), color);
|
||||
draw_list->AddLine(pos + ImVec2(highlight_width + 1, -1), pos + ImVec2(highlight_width + 1, s.LineHeight), ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Text)), 1.0F);
|
||||
}
|
||||
|
||||
if (addr - Cols < min)
|
||||
draw_list->AddLine(pos, pos + ImVec2(highlight_width + 1, 0), ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Text)), 1.0F);
|
||||
if (addr + Cols > max)
|
||||
draw_list->AddLine(pos + ImVec2(0, s.LineHeight), pos + ImVec2(highlight_width + 1, s.LineHeight), ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Text)), 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
if (DataEditingAddr == addr)
|
||||
@@ -689,8 +708,8 @@ struct MemoryEditor
|
||||
{
|
||||
IM_UNUSED(mem_data);
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
const char* format_range = OptUpperCaseHex ? "Range %0*" _PRISizeT "X..%0*" _PRISizeT "X" : "Range %0*" _PRISizeT "x..%0*" _PRISizeT "x";
|
||||
const char* format_selection = OptUpperCaseHex ? "Selection %0*" _PRISizeT "X..%0*" _PRISizeT "X (%ld %s)" : "Range %0*" _PRISizeT "x..%0*" _PRISizeT "x (%ld %s)";
|
||||
const char* format_range = OptUpperCaseHex ? "Range 0x%0*" _PRISizeT "X..0x%0*" _PRISizeT "X" : "Range 0x%0*" _PRISizeT "x..0x%0*" _PRISizeT "x";
|
||||
const char* format_selection = OptUpperCaseHex ? "Selection 0x%0*" _PRISizeT "X..0x%0*" _PRISizeT "X (%ld [0x%lX] %s)" : "Range 0x%0*" _PRISizeT "x..0x%0*" _PRISizeT "x (%ld [0x%lX] %s)";
|
||||
|
||||
if (this->OptShowExtraInfo) {
|
||||
ImGui::Text(format_range, s.AddrDigitsCount, base_display_addr, s.AddrDigitsCount, base_display_addr + mem_size - 1);
|
||||
@@ -703,7 +722,7 @@ struct MemoryEditor
|
||||
auto selectionEnd = std::max(DataPreviewAddr, DataPreviewAddrEnd);
|
||||
|
||||
size_t regionSize = (selectionEnd - selectionStart) + 1;
|
||||
ImGui::Text(format_selection, s.AddrDigitsCount, base_display_addr + selectionStart, s.AddrDigitsCount, base_display_addr + selectionEnd, regionSize, regionSize == 1 ? "byte" : "bytes");
|
||||
ImGui::Text(format_selection, s.AddrDigitsCount, base_display_addr + selectionStart, s.AddrDigitsCount, base_display_addr + selectionEnd, regionSize, regionSize, regionSize == 1 ? "byte" : "bytes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
24
external/ImGui/source/TextEditor.cpp
vendored
24
external/ImGui/source/TextEditor.cpp
vendored
@@ -767,8 +767,26 @@ void TextEditor::HandleKeyboardInputs()
|
||||
for (int i = 0; i < io.InputQueueCharacters.Size; i++)
|
||||
{
|
||||
auto c = io.InputQueueCharacters[i];
|
||||
if (c != 0 && (c == '\n' || c >= 32))
|
||||
EnterCharacter(c, shift);
|
||||
if (c != 0 && (c == '\n' || c >= 32)) {
|
||||
constexpr std::array<std::pair<char, char>, 5> doubleChars = {{ { '(', ')' }, { '[', ']' }, { '{', '}' }, { '"', '"' }, {'\'', '\'' } }};
|
||||
|
||||
bool handled = false;
|
||||
for (auto [doubleCharOpen, doubleCharClose] : doubleChars) {
|
||||
if (c == doubleCharOpen) {
|
||||
EnterCharacter(doubleCharOpen, shift);
|
||||
auto cursorPos = GetCursorPosition();
|
||||
EnterCharacter(doubleCharClose, shift);
|
||||
SetCursorPosition(cursorPos);
|
||||
|
||||
handled = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
EnterCharacter(c, shift);
|
||||
}
|
||||
}
|
||||
io.InputQueueCharacters.resize(0);
|
||||
}
|
||||
@@ -1872,7 +1890,7 @@ void TextEditor::Backspace()
|
||||
|
||||
u.mRemovedStart = u.mRemovedEnd = GetActualCursorCoordinates();
|
||||
--u.mRemovedStart.mColumn;
|
||||
--mState.mCursorPosition.mColumn;
|
||||
mState.mCursorPosition.mColumn = GetCharacterColumn(mState.mCursorPosition.mLine, cindex);
|
||||
|
||||
while (cindex < line.size() && cend-- > cindex)
|
||||
{
|
||||
|
||||
4598
external/ImGui/source/cimgui.cpp
vendored
Normal file
4598
external/ImGui/source/cimgui.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
53
external/ImGui/source/imgui_imhex_extensions.cpp
vendored
53
external/ImGui/source/imgui_imhex_extensions.cpp
vendored
@@ -15,6 +15,13 @@
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
|
||||
auto &mathInput = *static_cast<std::string*>(data->UserData);
|
||||
|
||||
mathInput.resize(data->BufTextLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool IconHyperlink(const char *icon, const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
@@ -401,7 +408,7 @@ namespace ImGui {
|
||||
return pressed;
|
||||
}
|
||||
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color, ImVec2 size_arg) {
|
||||
bool ToolBarButton(const char* symbol, ImVec4 color) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
@@ -415,7 +422,7 @@ namespace ImGui {
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
|
||||
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
ImVec2 size = CalcItemSize(ImVec2(1, 1) * ImGui::GetCurrentWindow()->MenuBarHeight(), label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImRect bb(pos, pos + size);
|
||||
ItemSize(size, style.FramePadding.y);
|
||||
@@ -443,4 +450,46 @@ namespace ImGui {
|
||||
return pressed;
|
||||
}
|
||||
|
||||
bool IconButton(const char* symbol, ImVec4 color, ImVec2 size_arg) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
color.w = 1.0F;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(symbol);
|
||||
const ImVec2 label_size = CalcTextSize(symbol, NULL, true);
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
|
||||
ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImRect bb(pos, pos + size);
|
||||
ItemSize(size, style.FramePadding.y);
|
||||
if (!ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
|
||||
|
||||
PushStyleColor(ImGuiCol_Text, color);
|
||||
|
||||
// Render
|
||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
RenderNavHighlight(bb, id);
|
||||
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
||||
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, symbol, NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
PopStyleColor();
|
||||
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
// CloseCurrentPopup();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return pressed;
|
||||
}
|
||||
|
||||
}
|
||||
10
external/ImGui/source/imgui_impl_glfw.cpp
vendored
10
external/ImGui/source/imgui_impl_glfw.cpp
vendored
@@ -472,10 +472,12 @@ static void ImGui_ImplGlfw_UpdateMouseCursor()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
#if !defined(OS_WINDOWS)
|
||||
// Show OS mouse cursor
|
||||
// FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
|
||||
glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
external/ImGui/source/imgui_impl_opengl3.cpp
vendored
2
external/ImGui/source/imgui_impl_opengl3.cpp
vendored
@@ -525,7 +525,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
|
||||
glGenTextures(1, &bd->FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
#endif
|
||||
|
||||
1
external/capstone
vendored
Submodule
1
external/capstone
vendored
Submodule
Submodule external/capstone added at 68102c05f1
2
external/curl
vendored
2
external/curl
vendored
Submodule external/curl updated: bfbde883af...aceff6088c
10
external/yara/CMakeLists.txt
vendored
10
external/yara/CMakeLists.txt
vendored
@@ -104,9 +104,11 @@ add_compile_definitions("MAGIC_MODULE")
|
||||
add_compile_definitions("MACHO_MODULE")
|
||||
add_compile_definitions("DEX_MODULE")
|
||||
|
||||
find_package(mbedTLS 2.26.0 REQUIRED)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-shift-count-overflow")
|
||||
add_library(libyara STATIC ${LIBYARA_SOURCE} ${LIBYARA_INCLUDES} ${LIBYARA_MODULES})
|
||||
set_property(TARGET libyara PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
target_include_directories(
|
||||
libyara
|
||||
@@ -114,13 +116,15 @@ target_include_directories(
|
||||
PRIVATE ${LIBYARA_SOURCE_PATH} ${MBEDTLS_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_directories(libyara PRIVATE ${MBEDTLS_LIBRARY_DIR})
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(libyara magic pthread)
|
||||
target_link_libraries(libyara PRIVATE magic ${MBEDTLS_LIBRARIES} pthread)
|
||||
else ()
|
||||
target_link_libraries(libyara magic)
|
||||
target_link_libraries(libyara PRIVATE magic ${MBEDTLS_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
configure_file(${LIBYARA_SOURCE_PATH}/yara.pc.in
|
||||
${LIBYARA_SOURCE_PATH}/yara.pc @ONLY)
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
class ViewHashes : public View {
|
||||
public:
|
||||
explicit ViewHashes();
|
||||
~ViewHashes() override;
|
||||
|
||||
void drawContent() override;
|
||||
void drawMenu() override;
|
||||
|
||||
private:
|
||||
bool m_shouldInvalidate = true;
|
||||
int m_currHashFunction = 0;
|
||||
u64 m_hashRegion[2] = { 0 };
|
||||
bool m_shouldMatchSelection = false;
|
||||
|
||||
static constexpr const char* HashFunctionNames[] = { "CRC16", "CRC32", "MD5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512" };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -25,7 +25,8 @@ namespace hex {
|
||||
|
||||
private:
|
||||
void setupNativeWindow();
|
||||
void updateNativeWindow();
|
||||
void beginNativeWindowFrame();
|
||||
void endNativeWindowFrame();
|
||||
void drawTitleBar();
|
||||
|
||||
void frameBegin();
|
||||
@@ -61,8 +62,8 @@ namespace hex {
|
||||
bool m_showTipOfTheDay;
|
||||
std::string m_tipOfTheDay;
|
||||
|
||||
ImGui::Texture m_bannerTexture;
|
||||
ImGui::Texture m_logoTexture;
|
||||
ImGui::Texture m_bannerTexture = { 0 };
|
||||
ImGui::Texture m_logoTexture = { 0 };
|
||||
|
||||
std::filesystem::path m_safetyBackupPath;
|
||||
|
||||
|
||||
@@ -13,6 +13,34 @@ add_library(${PROJECT_NAME} SHARED
|
||||
source/content/tools_entries.cpp
|
||||
source/content/data_processor_nodes.cpp
|
||||
source/content/ui_items.cpp
|
||||
source/content/providers.cpp
|
||||
source/content/views.cpp
|
||||
|
||||
source/content/providers/file_provider.cpp
|
||||
source/content/providers/gdb_provider.cpp
|
||||
source/content/providers/disk_provider.cpp
|
||||
|
||||
source/content/views/view_hexeditor.cpp
|
||||
source/content/views/view_pattern_editor.cpp
|
||||
source/content/views/view_pattern_data.cpp
|
||||
source/content/views/view_hashes.cpp
|
||||
source/content/views/view_information.cpp
|
||||
source/content/views/view_help.cpp
|
||||
source/content/views/view_tools.cpp
|
||||
source/content/views/view_strings.cpp
|
||||
source/content/views/view_data_inspector.cpp
|
||||
source/content/views/view_disassembler.cpp
|
||||
source/content/views/view_bookmarks.cpp
|
||||
source/content/views/view_patches.cpp
|
||||
source/content/views/view_command_palette.cpp
|
||||
source/content/views/view_settings.cpp
|
||||
source/content/views/view_data_processor.cpp
|
||||
source/content/views/view_yara.cpp
|
||||
source/content/views/view_constants.cpp
|
||||
source/content/views/view_store.cpp
|
||||
source/content/views/view_diff.cpp
|
||||
source/content/views/view_provider_settings.cpp
|
||||
|
||||
|
||||
source/math_evaluator.cpp
|
||||
|
||||
@@ -24,11 +52,10 @@ add_library(${PROJECT_NAME} SHARED
|
||||
|
||||
# Add additional include directories here #
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include)
|
||||
|
||||
# Add additional libraries here #
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE libimhex LLVMDemangle)
|
||||
|
||||
|
||||
|
||||
# ---- No need to change anything from here downwards unless you know what you're doing ---- #
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
63
plugins/builtin/include/content/providers/disk_provider.hpp
Normal file
63
plugins/builtin/include/content/providers/disk_provider.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
|
||||
class DiskProvider : public hex::prv::Provider {
|
||||
public:
|
||||
DiskProvider();
|
||||
~DiskProvider() override;
|
||||
|
||||
[[nodiscard]] bool isAvailable() const override;
|
||||
[[nodiscard]] bool isReadable() const override;
|
||||
[[nodiscard]] bool isWritable() const override;
|
||||
[[nodiscard]] bool isResizable() const override;
|
||||
[[nodiscard]] bool isSavable() const override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
[[nodiscard]] size_t getActualSize() const override;
|
||||
|
||||
void setPath(const std::string &path);
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] virtual std::string getName() const;
|
||||
[[nodiscard]] virtual std::vector<std::pair<std::string, std::string>> getDataInformation() const;
|
||||
|
||||
[[nodiscard]] bool hasLoadInterface() const override { return true; }
|
||||
void drawLoadInterface() override;
|
||||
|
||||
protected:
|
||||
void reloadDrives();
|
||||
|
||||
std::set<std::string> m_availableDrives;
|
||||
std::string m_path;
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
HANDLE m_diskHandle = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
int m_diskHandle = -1;
|
||||
#endif
|
||||
|
||||
size_t m_diskSize;
|
||||
size_t m_sectorSize;
|
||||
|
||||
u64 m_sectorBufferAddress;
|
||||
std::vector<u8> m_sectorBuffer;
|
||||
|
||||
bool m_readable = false;
|
||||
bool m_writable = false;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -14,18 +14,18 @@
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
namespace hex::prv {
|
||||
namespace hex::plugin::builtin::prv {
|
||||
|
||||
class FileProvider : public Provider {
|
||||
class FileProvider : public hex::prv::Provider {
|
||||
public:
|
||||
explicit FileProvider(std::string path);
|
||||
explicit FileProvider();
|
||||
~FileProvider() override;
|
||||
|
||||
bool isAvailable() const override;
|
||||
bool isReadable() const override;
|
||||
bool isWritable() const override;
|
||||
bool isResizable() const override;
|
||||
bool isSavable() const override;
|
||||
[[nodiscard]] bool isAvailable() const override;
|
||||
[[nodiscard]] bool isReadable() const override;
|
||||
[[nodiscard]] bool isWritable() const override;
|
||||
[[nodiscard]] bool isResizable() const override;
|
||||
[[nodiscard]] bool isSavable() const override;
|
||||
|
||||
void read(u64 offset, void *buffer, size_t size, bool overlays) override;
|
||||
void write(u64 offset, const void *buffer, size_t size) override;
|
||||
@@ -33,7 +33,7 @@ namespace hex::prv {
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
size_t getActualSize() const override;
|
||||
[[nodiscard]] size_t getActualSize() const override;
|
||||
|
||||
void save() override;
|
||||
void saveAs(const std::string &path) override;
|
||||
@@ -41,7 +41,12 @@ namespace hex::prv {
|
||||
[[nodiscard]] std::string getName() const override;
|
||||
[[nodiscard]] std::vector<std::pair<std::string, std::string>> getDataInformation() const override;
|
||||
|
||||
private:
|
||||
void setPath(const std::string &path);
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
void close() override;
|
||||
|
||||
protected:
|
||||
#if defined(OS_WINDOWS)
|
||||
HANDLE m_file = INVALID_HANDLE_VALUE;
|
||||
HANDLE m_mapping = INVALID_HANDLE_VALUE;
|
||||
@@ -54,12 +59,10 @@ namespace hex::prv {
|
||||
size_t m_fileSize = 0;
|
||||
|
||||
bool m_fileStatsValid = false;
|
||||
bool m_emptyFile = false;
|
||||
struct stat m_fileStats = { 0 };
|
||||
|
||||
bool m_readable = false, m_writable = false;
|
||||
|
||||
void open();
|
||||
void close();
|
||||
};
|
||||
|
||||
}
|
||||
65
plugins/builtin/include/content/providers/gdb_provider.hpp
Normal file
65
plugins/builtin/include/content/providers/gdb_provider.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/helpers/socket.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <mutex>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
|
||||
class GDBProvider : public hex::prv::Provider {
|
||||
public:
|
||||
explicit GDBProvider();
|
||||
~GDBProvider() override;
|
||||
|
||||
[[nodiscard]] bool isAvailable() const override;
|
||||
[[nodiscard]] bool isReadable() const override;
|
||||
[[nodiscard]] bool isWritable() const override;
|
||||
[[nodiscard]] bool isResizable() const override;
|
||||
[[nodiscard]] bool isSavable() const override;
|
||||
|
||||
void read(u64 offset, void *buffer, size_t size, bool overlays) override;
|
||||
void write(u64 offset, const void *buffer, size_t size) override;
|
||||
void resize(ssize_t newSize) override;
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
[[nodiscard]] size_t getActualSize() const override;
|
||||
|
||||
void save() override;
|
||||
void saveAs(const std::string &path) override;
|
||||
|
||||
[[nodiscard]] std::string getName() const override;
|
||||
[[nodiscard]] std::vector<std::pair<std::string, std::string>> getDataInformation() const override;
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] bool isConnected() const;
|
||||
|
||||
[[nodiscard]] bool hasLoadInterface() const override { return true; }
|
||||
void drawLoadInterface() override;
|
||||
|
||||
protected:
|
||||
hex::Socket m_socket;
|
||||
|
||||
std::string m_ipAddress;
|
||||
int m_port;
|
||||
|
||||
constexpr static size_t CacheLineSize = 0x1000;
|
||||
|
||||
struct CacheLine {
|
||||
u64 address;
|
||||
|
||||
std::array<u8, CacheLineSize> data;
|
||||
};
|
||||
|
||||
std::list<CacheLine> m_cache;
|
||||
|
||||
std::thread m_cacheUpdateThread;
|
||||
std::mutex m_cacheLock;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <tuple>
|
||||
#include <cstdio>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
enum class ConstantType {
|
||||
Int10,
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace hex {
|
||||
private:
|
||||
struct InspectorCacheEntry {
|
||||
std::string unlocalizedName;
|
||||
ContentRegistry::DataInspector::DisplayFunction displayFunction;
|
||||
ContentRegistry::DataInspector::impl::DisplayFunction displayFunction;
|
||||
};
|
||||
|
||||
bool m_shouldInvalidate = true;
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace hex {
|
||||
std::list<dp::Node*> m_nodes;
|
||||
std::list<dp::Link> m_links;
|
||||
|
||||
std::vector<prv::Overlay*> m_dataOverlays;
|
||||
std::vector<hex::prv::Overlay*> m_dataOverlays;
|
||||
|
||||
int m_rightClickedId = -1;
|
||||
ImVec2 m_rightClickedCoords;
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include "helpers/disassembler.hpp"
|
||||
#include <hex/helpers/disassembler.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -37,7 +37,12 @@ namespace hex {
|
||||
bool m_shouldMatchSelection = false;
|
||||
|
||||
Architecture m_architecture = Architecture::ARM;
|
||||
cs_mode m_modeBasicARM = cs_mode(0), m_modeExtraARM = cs_mode(0), m_modeBasicMIPS = cs_mode(0), m_modeBasicPPC = cs_mode(0), m_modeBasicX86 = cs_mode(0);
|
||||
cs_mode m_modeBasicARM = cs_mode(0);
|
||||
cs_mode m_modeExtraARM = cs_mode(0);
|
||||
cs_mode m_modeBasicMIPS = cs_mode(0);
|
||||
cs_mode m_modeBasicPPC = cs_mode(0);
|
||||
cs_mode m_modeBasicX86 = cs_mode(0);
|
||||
|
||||
bool m_littleEndianMode = true, m_micoMode = false, m_sparcV9Mode = false;
|
||||
|
||||
std::vector<Disassembly> m_disassembly;
|
||||
42
plugins/builtin/include/content/views/view_hashes.hpp
Normal file
42
plugins/builtin/include/content/views/view_hashes.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
#include <cstdio>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
class ViewHashes : public View {
|
||||
public:
|
||||
explicit ViewHashes();
|
||||
~ViewHashes() override;
|
||||
|
||||
void drawContent() override;
|
||||
void drawMenu() override;
|
||||
|
||||
private:
|
||||
enum class HashFunctions { Crc8, Crc16, Crc32, Md5, Sha1, Sha224, Sha256, Sha384, Sha512 };
|
||||
|
||||
bool m_shouldInvalidate = true;
|
||||
int m_currHashFunction = 0;
|
||||
u64 m_hashRegion[2] = { 0 };
|
||||
bool m_shouldMatchSelection = false;
|
||||
|
||||
static constexpr std::array hashFunctionNames {
|
||||
std::pair{HashFunctions::Crc8, "CRC8"},
|
||||
std::pair{HashFunctions::Crc16, "CRC16"},
|
||||
std::pair{HashFunctions::Crc32, "CRC32"},
|
||||
std::pair{HashFunctions::Md5, "MD5"},
|
||||
std::pair{HashFunctions::Sha1, "SHA-1"},
|
||||
std::pair{HashFunctions::Sha224, "SHA-224"},
|
||||
std::pair{HashFunctions::Sha256, "SHA-256"},
|
||||
std::pair{HashFunctions::Sha384, "SHA-384"},
|
||||
std::pair{HashFunctions::Sha512, "SHA-512"},
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <tuple>
|
||||
#include <cstdio>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -30,12 +30,13 @@ namespace hex {
|
||||
|
||||
private:
|
||||
bool m_aboutWindowOpen = false;
|
||||
bool m_patternHelpWindowOpen = false;
|
||||
bool m_mathHelpWindowOpen = false;
|
||||
|
||||
void drawAboutPopup();
|
||||
void drawPatternHelpPopup();
|
||||
void drawMathEvaluatorHelp();
|
||||
|
||||
void drawAboutMainPage();
|
||||
void drawContributorPage();
|
||||
void drawLibraryCreditsPage();
|
||||
void drawPathsPage();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex/views/view.hpp>
|
||||
#include "helpers/encoding_file.hpp"
|
||||
#include <hex/helpers/encoding_file.hpp>
|
||||
|
||||
#include <imgui_memory_editor.h>
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::prv { class Provider; }
|
||||
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
using SearchFunction = std::vector<std::pair<u64, u64>> (*)(prv::Provider* &provider, std::string string);
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -30,6 +31,7 @@ namespace hex {
|
||||
|
||||
std::array<ImU64, 256> m_valueCounts = { 0 };
|
||||
bool m_analyzing = false;
|
||||
std::atomic<u64> m_bytesAnalyzed;
|
||||
|
||||
std::pair<u64, u64> m_analyzedRegion = { 0, 0 };
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace hex {
|
||||
namespace prv { class Provider; }
|
||||
namespace lang { class PatternData; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewPatternData : public View {
|
||||
public:
|
||||
ViewPatternData();
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <TextEditor.h>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewPatternEditor : public View {
|
||||
public:
|
||||
@@ -37,6 +37,21 @@ namespace hex {
|
||||
TextEditor m_textEditor;
|
||||
std::vector<std::pair<pl::LogConsole::Level, std::string>> m_console;
|
||||
|
||||
enum class EnvVarType {
|
||||
Integer,
|
||||
Float,
|
||||
String,
|
||||
Bool
|
||||
};
|
||||
|
||||
struct EnvVar {
|
||||
std::string name;
|
||||
pl::Token::Literal value;
|
||||
EnvVarType type;
|
||||
};
|
||||
|
||||
std::vector<EnvVar> m_envVarEntries;
|
||||
|
||||
void loadPatternFile(const std::string &path);
|
||||
void clearPatternData();
|
||||
void parsePattern(char *buffer);
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewProviderSettings : public hex::View {
|
||||
public:
|
||||
ViewProviderSettings();
|
||||
~ViewProviderSettings();
|
||||
|
||||
void drawContent() override;
|
||||
void drawAlwaysVisible() override;
|
||||
|
||||
bool hasViewMenuItemEntry() override;
|
||||
|
||||
bool isAvailable();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewSettings : public View {
|
||||
public:
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
struct StoreEntry {
|
||||
std::string name;
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace hex {
|
||||
|
||||
private:
|
||||
bool m_searching = false;
|
||||
bool m_regex = false;
|
||||
bool m_pattern_parsed = false;
|
||||
|
||||
std::vector<FoundString> m_foundStrings;
|
||||
std::vector<size_t> m_filterIndices;
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <imgui.h>
|
||||
#include <hex/views/view.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
class ViewYara : public View {
|
||||
public:
|
||||
@@ -18,6 +18,7 @@ namespace hex {
|
||||
private:
|
||||
struct YaraMatch {
|
||||
std::string identifier;
|
||||
std::string variable;
|
||||
s64 address;
|
||||
s32 size;
|
||||
bool wholeDataMatch;
|
||||
@@ -28,9 +28,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
|
||||
if (result.has_value())
|
||||
return hex::format("#{0} = %{1}", input.data(), result.value());
|
||||
return hex::format("#{0} = {1}", input.data(), result.value());
|
||||
else
|
||||
return hex::format("#{0} = ???", input.data());
|
||||
return std::string("???");
|
||||
});
|
||||
|
||||
ContentRegistry::CommandPaletteCommands::add(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <hex/helpers/shared_data.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
#include <hex/pattern_language/token.hpp>
|
||||
#include <hex/pattern_language/log_console.hpp>
|
||||
@@ -15,7 +16,7 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
std::string format(pl::Evaluator *, auto params) {
|
||||
std::string format(pl::Evaluator *ctx, auto params) {
|
||||
auto format = pl::Token::literalToString(params[0], true);
|
||||
std::string message;
|
||||
|
||||
@@ -26,7 +27,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::visit(overloaded {
|
||||
[&](pl::PatternData* value) {
|
||||
formatArgs.push_back(hex::format("{} {} @ 0x{:X}", value->getTypeName(), value->getVariableName(), value->getOffset()));
|
||||
formatArgs.push_back(value->toString(ctx->getProvider()));
|
||||
},
|
||||
[&](auto &&value) {
|
||||
formatArgs.push_back(value);
|
||||
@@ -50,7 +51,7 @@ namespace hex::plugin::builtin {
|
||||
/* assert(condition, message) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStd, "assert", 2, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto condition = Token::literalToBoolean(params[0]);
|
||||
auto message = std::get<std::string>(params[1]);
|
||||
auto message = Token::literalToString(params[1], false);
|
||||
|
||||
if (!condition)
|
||||
LogConsole::abortEvaluation(hex::format("assertion failed \"{0}\"", message));
|
||||
@@ -61,7 +62,7 @@ namespace hex::plugin::builtin {
|
||||
/* assert_warn(condition, message) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStd, "assert_warn", 2, [](auto *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto condition = Token::literalToBoolean(params[0]);
|
||||
auto message = std::get<std::string>(params[1]);
|
||||
auto message = Token::literalToString(params[1], false);
|
||||
|
||||
if (!condition)
|
||||
ctx->getConsole().log(LogConsole::Level::Warning, hex::format("assertion failed \"{0}\"", message));
|
||||
@@ -81,6 +82,13 @@ namespace hex::plugin::builtin {
|
||||
return format(ctx, params);
|
||||
});
|
||||
|
||||
/* env(name) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStd, "env", 1, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
auto name = Token::literalToString(params[0], false);
|
||||
|
||||
return ctx->getEnvVariable(name);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
ContentRegistry::PatternLanguageFunctions::Namespace nsStdMem = { "std", "mem" };
|
||||
@@ -192,7 +200,14 @@ namespace hex::plugin::builtin {
|
||||
auto string = Token::literalToString(params[0], false);
|
||||
auto index = Token::literalToSigned(params[1]);
|
||||
|
||||
if (std::abs(index) >= string.length())
|
||||
#if defined(OS_MACOS)
|
||||
const auto signIndex = index >> (sizeof(index) * 8 - 1);
|
||||
const auto absIndex = (index ^ signIndex) - signIndex;
|
||||
#else
|
||||
const auto absIndex = std::abs(index);
|
||||
#endif
|
||||
|
||||
if (absIndex > string.length())
|
||||
LogConsole::abortEvaluation("character index out of range");
|
||||
|
||||
if (index >= 0)
|
||||
@@ -240,6 +255,135 @@ namespace hex::plugin::builtin {
|
||||
return net.getString(url).get().body;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ContentRegistry::PatternLanguageFunctions::Namespace nsStdFile = { "std", "file" };
|
||||
{
|
||||
|
||||
static u32 fileCounter = 0;
|
||||
static std::map<u32, File> openFiles;
|
||||
|
||||
/* open(path, mode) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "open", 2, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto path = Token::literalToString(params[0], false);
|
||||
const auto modeEnum = Token::literalToUnsigned(params[1]);
|
||||
|
||||
File::Mode mode;
|
||||
switch (modeEnum) {
|
||||
case 1: mode = File::Mode::Read; break;
|
||||
case 2: mode = File::Mode::Write; break;
|
||||
case 3: mode = File::Mode::Create; break;
|
||||
default:
|
||||
LogConsole::abortEvaluation("invalid file open mode");
|
||||
}
|
||||
|
||||
auto file = File(path, mode);
|
||||
|
||||
if (!file.isValid())
|
||||
LogConsole::abortEvaluation(hex::format("failed to open file {}", path));
|
||||
|
||||
fileCounter++;
|
||||
openFiles.emplace(std::pair{ fileCounter, std::move(file) });
|
||||
|
||||
return u128(fileCounter);
|
||||
});
|
||||
|
||||
/* close(file) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "close", 1, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles.erase(file);
|
||||
|
||||
return { };
|
||||
});
|
||||
|
||||
/* read(file, size) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "read", 2, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
return openFiles[file].readString(size);
|
||||
});
|
||||
|
||||
/* write(file, data) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "write", 2, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto data = Token::literalToString(params[1], true);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].write(data);
|
||||
|
||||
return { };
|
||||
});
|
||||
|
||||
/* seek(file, offset) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "seek", 2, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto offset = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].seek(offset);
|
||||
|
||||
return { };
|
||||
});
|
||||
|
||||
/* size(file) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "size", 1, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
return u128(openFiles[file].getSize());
|
||||
});
|
||||
|
||||
/* resize(file, size) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "resize", 2, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
const auto size = Token::literalToUnsigned(params[1]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].setSize(size);
|
||||
|
||||
return { };
|
||||
});
|
||||
|
||||
/* flush(file) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "flush", 1, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].flush();
|
||||
|
||||
return { };
|
||||
});
|
||||
|
||||
/* remove(file) */
|
||||
ContentRegistry::PatternLanguageFunctions::add(nsStdFile, "remove", 1, [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
|
||||
const auto file = Token::literalToUnsigned(params[0]);
|
||||
|
||||
if (!openFiles.contains(file))
|
||||
LogConsole::abortEvaluation("failed to access invalid file");
|
||||
|
||||
openFiles[file].remove();
|
||||
|
||||
return { };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
17
plugins/builtin/source/content/providers.cpp
Normal file
17
plugins/builtin/source/content/providers.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include "content/providers/gdb_provider.hpp"
|
||||
#include "content/providers/file_provider.hpp"
|
||||
#include "content/providers/disk_provider.hpp"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
void registerProviders() {
|
||||
|
||||
ContentRegistry::Provider::add<prv::FileProvider>("hex.builtin.provider.file", false);
|
||||
ContentRegistry::Provider::add<prv::GDBProvider>("hex.builtin.provider.gdb");
|
||||
ContentRegistry::Provider::add<prv::DiskProvider>("hex.builtin.provider.disk");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
322
plugins/builtin/source/content/providers/disk_provider.cpp
Normal file
322
plugins/builtin/source/content/providers/disk_provider.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
#include "content/providers/disk_provider.hpp"
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <bitset>
|
||||
#include <filesystem>
|
||||
|
||||
#if defined (OS_LINUX)
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define lseek lseek64
|
||||
#elif defined (OS_MACOS)
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
|
||||
DiskProvider::DiskProvider() : Provider() {
|
||||
this->reloadDrives();
|
||||
}
|
||||
|
||||
DiskProvider::~DiskProvider() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
bool DiskProvider::isAvailable() const {
|
||||
#if defined (OS_WINDOWS)
|
||||
return this->m_diskHandle != INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
return this->m_diskHandle != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DiskProvider::isReadable() const {
|
||||
return this->m_readable;
|
||||
}
|
||||
|
||||
bool DiskProvider::isWritable() const {
|
||||
return this->m_writable;
|
||||
}
|
||||
|
||||
bool DiskProvider::isResizable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DiskProvider::isSavable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DiskProvider::setPath(const std::string &path) {
|
||||
this->m_path = path;
|
||||
}
|
||||
|
||||
bool DiskProvider::open() {
|
||||
this->m_readable = true;
|
||||
this->m_writable = true;
|
||||
|
||||
#if defined (OS_WINDOWS)
|
||||
|
||||
std::wstring widePath;
|
||||
{
|
||||
auto length = this->m_path.length() + 1;
|
||||
auto wideLength = MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, 0, 0);
|
||||
auto buffer = new wchar_t[wideLength];
|
||||
MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, buffer, wideLength);
|
||||
widePath = buffer;
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
this->m_diskHandle = reinterpret_cast<HANDLE>(CreateFileW(widePath.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
|
||||
if (this->m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
this->m_diskHandle = reinterpret_cast<HANDLE>(CreateFileW(widePath.data(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
|
||||
this->m_writable = false;
|
||||
|
||||
if (this->m_diskHandle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
DISK_GEOMETRY_EX diskGeometry = { 0 };
|
||||
DWORD bytesRead = 0;
|
||||
if (DeviceIoControl(
|
||||
this->m_diskHandle,
|
||||
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
||||
nullptr, 0,
|
||||
&diskGeometry, sizeof(DISK_GEOMETRY_EX),
|
||||
&bytesRead,
|
||||
nullptr))
|
||||
{
|
||||
this->m_diskSize = diskGeometry.DiskSize.QuadPart;
|
||||
this->m_sectorSize = diskGeometry.Geometry.BytesPerSector;
|
||||
this->m_sectorBuffer.resize(this->m_sectorSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_diskHandle == nullptr || this->m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
this->m_readable = false;
|
||||
this->m_diskHandle = nullptr;
|
||||
CloseHandle(this->m_diskHandle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else
|
||||
struct stat driveStat;
|
||||
|
||||
::stat(this->m_path.data(), &driveStat) == 0;
|
||||
this->m_diskSize = driveStat.st_size;
|
||||
this->m_sectorSize = 0;
|
||||
|
||||
this->m_diskHandle = ::open(this->m_path.data(), O_RDWR);
|
||||
if (this->m_diskHandle == -1) {
|
||||
this->m_diskHandle = ::open(this->m_path.data(), O_RDONLY);
|
||||
this->m_writable = false;
|
||||
}
|
||||
|
||||
if (this->m_diskHandle == -1) {
|
||||
this->m_readable = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiskProvider::close() {
|
||||
#if defined (OS_WINDOWS)
|
||||
if (this->m_diskHandle != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(this->m_diskHandle);
|
||||
|
||||
this->m_diskHandle = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
if (this->m_diskHandle != -1)
|
||||
::close(this->m_diskHandle);
|
||||
|
||||
this->m_diskHandle = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DiskProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
#if defined (OS_WINDOWS)
|
||||
DWORD bytesRead = 0;
|
||||
|
||||
u64 startOffset = offset;
|
||||
|
||||
while (size > 0) {
|
||||
LARGE_INTEGER seekPosition;
|
||||
seekPosition.LowPart = (offset & 0xFFFF'FFFF) - (offset % this->m_sectorSize);
|
||||
seekPosition.HighPart = offset >> 32;
|
||||
|
||||
if (this->m_sectorBufferAddress != seekPosition.QuadPart) {
|
||||
::SetFilePointer(this->m_diskHandle, seekPosition.LowPart, &seekPosition.HighPart, FILE_BEGIN);
|
||||
::ReadFile(this->m_diskHandle, this->m_sectorBuffer.data(), this->m_sectorBuffer.size(), &bytesRead, nullptr);
|
||||
this->m_sectorBufferAddress = seekPosition.QuadPart;
|
||||
}
|
||||
|
||||
std::memcpy(reinterpret_cast<u8*>(buffer) + (offset - startOffset), this->m_sectorBuffer.data() + (offset & (this->m_sectorSize - 1)), std::min(this->m_sectorSize, size));
|
||||
|
||||
size = std::max<ssize_t>(static_cast<ssize_t>(size) - this->m_sectorSize, 0);
|
||||
offset += this->m_sectorSize;
|
||||
}
|
||||
#else
|
||||
u64 startOffset = offset;
|
||||
|
||||
while (size > 0) {
|
||||
u64 seekPosition = offset - (offset % this->m_sectorSize);
|
||||
|
||||
if (this->m_sectorBufferAddress != seekPosition) {
|
||||
::lseek(this->m_diskHandle, seekPosition, SEEK_SET);
|
||||
::read(this->m_diskHandle, buffer, size);
|
||||
this->m_sectorBufferAddress = seekPosition;
|
||||
}
|
||||
|
||||
std::memcpy(reinterpret_cast<u8*>(buffer) + (offset - startOffset), this->m_sectorBuffer.data() + (offset & (this->m_sectorSize - 1)), std::min(this->m_sectorSize, size));
|
||||
|
||||
size = std::max<ssize_t>(static_cast<ssize_t>(size) - this->m_sectorSize, 0);
|
||||
offset += this->m_sectorSize;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DiskProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
#if defined (OS_WINDOWS)
|
||||
DWORD bytesWritten = 0;
|
||||
|
||||
u64 startOffset = offset;
|
||||
|
||||
std::vector<u8> modifiedSectorBuffer;
|
||||
modifiedSectorBuffer.resize(this->m_sectorSize);
|
||||
|
||||
while (size > 0) {
|
||||
u64 sectorBase = offset - (offset % this->m_sectorSize);
|
||||
size_t currSize = std::min(size, this->m_sectorSize);
|
||||
|
||||
this->readRaw(sectorBase, modifiedSectorBuffer.data(), modifiedSectorBuffer.size());
|
||||
std::memcpy(modifiedSectorBuffer.data() + ((offset - sectorBase) % this->m_sectorSize), reinterpret_cast<const u8*>(buffer) + (startOffset - offset), currSize);
|
||||
|
||||
LARGE_INTEGER seekPosition;
|
||||
seekPosition.LowPart = (offset & 0xFFFF'FFFF) - (offset % this->m_sectorSize);
|
||||
seekPosition.HighPart = offset >> 32;
|
||||
|
||||
::SetFilePointer(this->m_diskHandle, seekPosition.LowPart, &seekPosition.HighPart, FILE_BEGIN);
|
||||
::WriteFile(this->m_diskHandle, modifiedSectorBuffer.data(), modifiedSectorBuffer.size(), &bytesWritten, nullptr);
|
||||
|
||||
offset += currSize;
|
||||
size -= currSize;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
u64 startOffset = offset;
|
||||
|
||||
std::vector<u8> modifiedSectorBuffer;
|
||||
modifiedSectorBuffer.resize(this->m_sectorSize);
|
||||
|
||||
while (size > 0) {
|
||||
u64 sectorBase = offset - (offset % this->m_sectorSize);
|
||||
size_t currSize = std::min(size, this->m_sectorSize);
|
||||
|
||||
this->readRaw(sectorBase, modifiedSectorBuffer.data(), modifiedSectorBuffer.size());
|
||||
std::memcpy(modifiedSectorBuffer.data() + ((offset - sectorBase) % this->m_sectorSize), reinterpret_cast<const u8*>(buffer) + (startOffset - offset), currSize);
|
||||
|
||||
::lseek(this->m_diskHandle, sectorBase, SEEK_SET);
|
||||
::write(this->m_diskHandle, modifiedSectorBuffer.data(), modifiedSectorBuffer.size());
|
||||
|
||||
offset += currSize;
|
||||
size -= currSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t DiskProvider::getActualSize() const {
|
||||
return this->m_diskSize;
|
||||
}
|
||||
|
||||
std::string DiskProvider::getName() const {
|
||||
return this->m_path;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> DiskProvider::getDataInformation() const {
|
||||
return {
|
||||
{ "hex.builtin.provider.disk.selected_disk"_lang, this->m_path },
|
||||
{ "hex.builtin.provider.disk.disk_size"_lang, hex::toByteString(this->m_diskSize) },
|
||||
{ "hex.builtin.provider.disk.sector_size"_lang, hex::toByteString(this->m_sectorSize) }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void DiskProvider::reloadDrives() {
|
||||
#if defined (OS_WINDOWS)
|
||||
this->m_availableDrives.clear();
|
||||
std::bitset<32> drives = ::GetLogicalDrives();
|
||||
for (char i = 0; i < 26; i++) {
|
||||
if (drives[i])
|
||||
this->m_availableDrives.insert(hex::format(R"(\\.\{:c}:)", 'A' + i));
|
||||
}
|
||||
|
||||
auto logicalDrives = this->m_availableDrives;
|
||||
for (const auto &drive : logicalDrives) {
|
||||
auto handle = reinterpret_cast<HANDLE>(::CreateFile(drive.data(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr));
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) continue;
|
||||
|
||||
VOLUME_DISK_EXTENTS diskExtents = { 0 };
|
||||
DWORD bytesRead = 0;
|
||||
auto result = ::DeviceIoControl(
|
||||
handle,
|
||||
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
|
||||
nullptr,
|
||||
0,
|
||||
&diskExtents,
|
||||
sizeof(VOLUME_DISK_EXTENTS),
|
||||
&bytesRead,
|
||||
nullptr);
|
||||
|
||||
if (result) {
|
||||
auto diskPath = hex::format(R"(\\.\PhysicalDrive{})", diskExtents.Extents[0].DiskNumber);
|
||||
this->m_availableDrives.insert(diskPath);
|
||||
}
|
||||
|
||||
::CloseHandle(handle);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DiskProvider::drawLoadInterface() {
|
||||
#if defined (OS_WINDOWS)
|
||||
if (ImGui::BeginListBox("hex.builtin.provider.disk.selected_disk"_lang)) {
|
||||
|
||||
for (const auto &drive : this->m_availableDrives) {
|
||||
if (ImGui::Selectable(drive.c_str(), this->m_path == drive))
|
||||
this->m_path = drive;
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.builtin.provider.disk.reload"_lang)) {
|
||||
this->reloadDrives();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
ImGui::InputText("hex.builtin.provider.disk.selected_disk"_lang, this->m_path.data(), this->m_path.capacity(), ImGuiInputTextFlags_CallbackResize, ImGui::UpdateStringSizeCallback, &this->m_path);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "providers/file_provider.hpp"
|
||||
#include "content/providers/file_provider.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <cstring>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include "helpers/project_file_handler.hpp"
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
|
||||
namespace hex::prv {
|
||||
namespace hex::plugin::builtin::prv {
|
||||
|
||||
FileProvider::FileProvider() : Provider() {
|
||||
|
||||
FileProvider::FileProvider(std::string path) : Provider(), m_path(std::move(path)) {
|
||||
this->open();
|
||||
}
|
||||
|
||||
FileProvider::~FileProvider() {
|
||||
@@ -20,7 +20,7 @@ namespace hex::prv {
|
||||
|
||||
bool FileProvider::isAvailable() const {
|
||||
#if defined(OS_WINDOWS)
|
||||
return this->m_file != nullptr && this->m_mapping != nullptr && this->m_mappedFile != nullptr;
|
||||
return this->m_file != INVALID_HANDLE_VALUE && this->m_mapping != INVALID_HANDLE_VALUE && this->m_mappedFile != nullptr;
|
||||
#else
|
||||
return this->m_file != -1 && this->m_mappedFile != nullptr;
|
||||
#endif
|
||||
@@ -44,11 +44,10 @@ namespace hex::prv {
|
||||
|
||||
|
||||
void FileProvider::read(u64 offset, void *buffer, size_t size, bool overlays) {
|
||||
|
||||
if ((offset - this->getBaseAddress()) > (this->getSize() - size) || buffer == nullptr || size == 0)
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset - this->getBaseAddress(), size);
|
||||
this->readRaw(offset - this->getBaseAddress(), buffer, size);
|
||||
|
||||
for (u64 i = 0; i < size; i++)
|
||||
if (getPatches().contains(offset + i))
|
||||
@@ -59,25 +58,21 @@ namespace hex::prv {
|
||||
}
|
||||
|
||||
void FileProvider::write(u64 offset, const void *buffer, size_t size) {
|
||||
if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
addPatch(offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset, size);
|
||||
}
|
||||
|
||||
void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
if ((offset + size) > this->getSize() || buffer == nullptr || size == 0)
|
||||
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(reinterpret_cast<u8*>(this->m_mappedFile) + PageSize * this->m_currPage + offset, buffer, size);
|
||||
@@ -91,15 +86,16 @@ namespace hex::prv {
|
||||
File file(path, File::Mode::Create);
|
||||
|
||||
if (file.isValid()) {
|
||||
std::vector<u8> buffer(std::min<size_t>(0xFF'FFFF, file.getSize()), 0x00);
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
std::vector<u8> buffer(std::min<size_t>(0xFF'FFFF, provider->getActualSize()), 0x00);
|
||||
size_t bufferSize = buffer.size();
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
for (u64 offset = 0; offset < provider->getActualSize(); offset += bufferSize) {
|
||||
if (bufferSize > provider->getActualSize() - offset)
|
||||
bufferSize = provider->getActualSize() - offset;
|
||||
|
||||
provider->readRelative(offset, buffer.data(), bufferSize);
|
||||
provider->read(offset + this->getBaseAddress(), buffer.data(), bufferSize);
|
||||
file.write(buffer);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +156,11 @@ namespace hex::prv {
|
||||
return result;
|
||||
}
|
||||
|
||||
void FileProvider::open() {
|
||||
void FileProvider::setPath(const std::string &path) {
|
||||
this->m_path = path;
|
||||
}
|
||||
|
||||
bool FileProvider::open() {
|
||||
this->m_fileStatsValid = stat(this->m_path.data(), &this->m_fileStats) == 0;
|
||||
|
||||
this->m_readable = true;
|
||||
@@ -197,33 +197,41 @@ namespace hex::prv {
|
||||
};
|
||||
|
||||
if (this->m_file == nullptr || this->m_file == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_mapping = CreateFileMapping(this->m_file, nullptr, PAGE_READWRITE, fileSize.HighPart, fileSize.LowPart, nullptr);
|
||||
if (this->m_mapping == nullptr || this->m_mapping == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
if (this->m_fileSize > 0) {
|
||||
this->m_mapping = CreateFileMapping(this->m_file, nullptr, PAGE_READWRITE, fileSize.HighPart, fileSize.LowPart, nullptr);
|
||||
if (this->m_mapping == nullptr || this->m_mapping == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mappingCleanup = SCOPE_GUARD {
|
||||
this->m_readable = false;
|
||||
this->m_mapping = nullptr;
|
||||
CloseHandle(this->m_mapping);
|
||||
};
|
||||
auto mappingCleanup = SCOPE_GUARD {
|
||||
this->m_readable = false;
|
||||
this->m_mapping = nullptr;
|
||||
CloseHandle(this->m_mapping);
|
||||
};
|
||||
|
||||
this->m_mappedFile = MapViewOfFile(this->m_mapping, FILE_MAP_ALL_ACCESS, 0, 0, this->m_fileSize);
|
||||
if (this->m_mappedFile == nullptr) {
|
||||
this->m_readable = false;
|
||||
return;
|
||||
this->m_mappedFile = MapViewOfFile(this->m_mapping, FILE_MAP_ALL_ACCESS, 0, 0, this->m_fileSize);
|
||||
if (this->m_mappedFile == nullptr) {
|
||||
this->m_readable = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
mappingCleanup.release();
|
||||
|
||||
ProjectFile::setFilePath(this->m_path);
|
||||
} else if (!this->m_emptyFile) {
|
||||
this->m_emptyFile = true;
|
||||
this->resize(1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
fileCleanup.release();
|
||||
mappingCleanup.release();
|
||||
|
||||
ProjectFile::setFilePath(this->m_path);
|
||||
|
||||
#else
|
||||
this->m_file = ::open(this->m_path.data(), O_RDWR);
|
||||
this->m_file = ::open(this->m_path.data(), O_RDWR);
|
||||
if (this->m_file == -1) {
|
||||
this->m_file = ::open(this->m_path.data(), O_RDONLY);
|
||||
this->m_writable = false;
|
||||
@@ -231,14 +239,21 @@ namespace hex::prv {
|
||||
|
||||
if (this->m_file == -1) {
|
||||
this->m_readable = false;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->m_fileSize = this->m_fileStats.st_size;
|
||||
|
||||
this->m_mappedFile = mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0);
|
||||
this->m_mappedFile = ::mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0);
|
||||
if (this->m_mappedFile == nullptr) {
|
||||
::close(this->m_file);
|
||||
this->m_file = -1;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileProvider::close() {
|
||||
312
plugins/builtin/source/content/providers/gdb_provider.cpp
Normal file
312
plugins/builtin/source/content/providers/gdb_provider.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
#include "content/providers/gdb_provider.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::prv {
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace gdb {
|
||||
|
||||
namespace {
|
||||
|
||||
u8 calculateChecksum(const std::string &data) {
|
||||
u64 checksum = 0;
|
||||
|
||||
for (const auto &c : data)
|
||||
checksum += c;
|
||||
|
||||
return checksum & 0xFF;
|
||||
}
|
||||
|
||||
std::string createPacket(const std::string &data) {
|
||||
return hex::format("${}#{:02x}", data, calculateChecksum(data));
|
||||
}
|
||||
|
||||
std::optional<std::string> parsePacket(const std::string &packet) {
|
||||
if (packet.length() < 4)
|
||||
return std::nullopt;
|
||||
|
||||
if (!packet.starts_with('$'))
|
||||
return std::nullopt;
|
||||
|
||||
if (packet[packet.length() - 3] != '#')
|
||||
return std::nullopt;
|
||||
|
||||
std::string data = packet.substr(1, packet.length() - 4);
|
||||
std::string checksum = packet.substr(packet.length() - 2, 2);
|
||||
|
||||
if (checksum.length() != 2 || crypt::decode16(checksum)[0] != calculateChecksum(data))
|
||||
return std::nullopt;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sendAck(Socket &socket) {
|
||||
socket.writeString("+");
|
||||
}
|
||||
|
||||
std::vector<u8> readMemory(Socket &socket, u64 address, size_t size) {
|
||||
std::string packet = createPacket(hex::format("m{:X},{:X}", address, size));
|
||||
|
||||
socket.writeString(packet);
|
||||
|
||||
auto receivedPacket = socket.readString(size * 2 + 4);
|
||||
|
||||
if (receivedPacket.empty())
|
||||
return { };
|
||||
|
||||
auto receivedData = parsePacket(receivedPacket);
|
||||
if (!receivedData.has_value())
|
||||
return { };
|
||||
|
||||
if (receivedData->size() == 3 && receivedData->starts_with("E"))
|
||||
return { };
|
||||
|
||||
auto data = crypt::decode16(receivedData.value());
|
||||
|
||||
data.resize(size);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void writeMemory(Socket &socket, u64 address, const void *buffer, size_t size) {
|
||||
std::vector<u8> bytes(size);
|
||||
std::memcpy(bytes.data(), buffer, size);
|
||||
|
||||
std::string byteString = crypt::encode16(bytes);
|
||||
|
||||
std::string packet = createPacket(hex::format("M{:X},{:X}:{}", address, size, byteString));
|
||||
|
||||
socket.writeString(packet);
|
||||
|
||||
auto receivedPacket = socket.readString(3);
|
||||
}
|
||||
|
||||
bool enableNoAckMode(Socket &socket) {
|
||||
socket.writeString(createPacket("QStartNoAckMode"));
|
||||
|
||||
auto ack = socket.readString(1);
|
||||
|
||||
if (ack.empty() || ack[0] != '+')
|
||||
return {};
|
||||
|
||||
auto receivedPacket = socket.readString(6);
|
||||
|
||||
auto receivedData = parsePacket(receivedPacket);
|
||||
|
||||
if (receivedData && *receivedData == "OK") {
|
||||
sendAck(socket);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GDBProvider::GDBProvider() : Provider() {
|
||||
|
||||
}
|
||||
|
||||
GDBProvider::~GDBProvider() {
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
bool GDBProvider::isAvailable() const {
|
||||
return this->m_socket.isConnected();
|
||||
}
|
||||
|
||||
bool GDBProvider::isReadable() const {
|
||||
return this->m_socket.isConnected();
|
||||
}
|
||||
|
||||
bool GDBProvider::isWritable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GDBProvider::isResizable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GDBProvider::isSavable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void GDBProvider::read(u64 offset, void *buffer, size_t size, bool overlays) {
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
u64 alignedOffset = offset - (offset % CacheLineSize);
|
||||
|
||||
if (size <= CacheLineSize) {
|
||||
std::scoped_lock lock(this->m_cacheLock);
|
||||
|
||||
const auto &cacheLine = std::find_if(this->m_cache.begin(), this->m_cache.end(), [&](auto &line){
|
||||
return line.address == alignedOffset;
|
||||
});
|
||||
|
||||
if (cacheLine != this->m_cache.end()) {
|
||||
// Cache hit
|
||||
|
||||
} else {
|
||||
// Cache miss
|
||||
|
||||
this->m_cache.push_back({ alignedOffset, { 0 } });
|
||||
}
|
||||
|
||||
if (cacheLine != this->m_cache.end())
|
||||
std::memcpy(buffer, &cacheLine->data[0] + (offset % CacheLineSize), size);
|
||||
} else {
|
||||
while (size > 0) {
|
||||
size_t readSize = std::min(size, CacheLineSize);
|
||||
this->readRaw(offset, buffer, readSize);
|
||||
|
||||
size -= readSize;
|
||||
offset += readSize;
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < size; i++)
|
||||
if (getPatches().contains(offset + i))
|
||||
reinterpret_cast<u8*>(buffer)[i] = getPatches()[offset + PageSize * this->m_currPage + i];
|
||||
|
||||
if (overlays)
|
||||
this->applyOverlays(offset, buffer, size);
|
||||
}
|
||||
|
||||
void GDBProvider::write(u64 offset, const void *buffer, size_t size) {
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
gdb::writeMemory(this->m_socket, offset, buffer, size);
|
||||
}
|
||||
|
||||
void GDBProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
auto data = gdb::readMemory(this->m_socket, offset, size);
|
||||
std::memcpy(buffer, &data[0], data.size());
|
||||
}
|
||||
|
||||
void GDBProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
gdb::writeMemory(this->m_socket, offset, buffer, size);
|
||||
}
|
||||
|
||||
void GDBProvider::save() {
|
||||
this->applyPatches();
|
||||
}
|
||||
|
||||
void GDBProvider::saveAs(const std::string &path) {
|
||||
|
||||
}
|
||||
|
||||
void GDBProvider::resize(ssize_t newSize) {
|
||||
|
||||
}
|
||||
|
||||
size_t GDBProvider::getActualSize() const {
|
||||
return 0xFFFF'FFFF;
|
||||
}
|
||||
|
||||
std::string GDBProvider::getName() const {
|
||||
std::string address, port;
|
||||
|
||||
if (!this->isConnected()) {
|
||||
address = "-";
|
||||
port = "-";
|
||||
} else {
|
||||
address = this->m_ipAddress;
|
||||
port = std::to_string(this->m_port);
|
||||
}
|
||||
|
||||
return hex::format("hex.builtin.provider.gdb.name"_lang, address, port);
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> GDBProvider::getDataInformation() const {
|
||||
return {
|
||||
{ "hex.builtin.provider.gdb.server"_lang, hex::format("{}:{}", this->m_ipAddress, this->m_port) },
|
||||
};
|
||||
}
|
||||
|
||||
bool GDBProvider::open() {
|
||||
this->m_socket.connect(this->m_ipAddress, this->m_port);
|
||||
if (!gdb::enableNoAckMode(this->m_socket)) {
|
||||
this->m_socket.disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->m_socket.isConnected()) {
|
||||
this->m_cacheUpdateThread = std::thread([this]() {
|
||||
auto cacheLine = this->m_cache.begin();
|
||||
while (this->isConnected()) {
|
||||
{
|
||||
std::scoped_lock lock(this->m_cacheLock);
|
||||
|
||||
if (cacheLine != this->m_cache.end()) {
|
||||
auto data = gdb::readMemory(this->m_socket, cacheLine->address, 0x1000);
|
||||
|
||||
while (this->m_cache.size() > 10) {
|
||||
this->m_cache.pop_front();
|
||||
cacheLine = this->m_cache.begin();
|
||||
}
|
||||
|
||||
std::memcpy(cacheLine->data.data(), data.data(), data.size());
|
||||
}
|
||||
|
||||
cacheLine++;
|
||||
if (cacheLine == this->m_cache.end())
|
||||
cacheLine = this->m_cache.begin();
|
||||
}
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GDBProvider::close() {
|
||||
this->m_socket.disconnect();
|
||||
|
||||
if (this->m_cacheUpdateThread.joinable()) {
|
||||
this->m_cacheUpdateThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBProvider::isConnected() const {
|
||||
return this->m_socket.isConnected();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GDBProvider::drawLoadInterface() {
|
||||
ImGui::InputText("hex.builtin.provider.gdb.ip"_lang, this->m_ipAddress.data(), this->m_ipAddress.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &this->m_ipAddress);
|
||||
ImGui::InputInt("hex.builtin.provider.gdb.port"_lang, &this->m_port, 0, 0);
|
||||
|
||||
if (this->m_port < 0)
|
||||
this->m_port = 0;
|
||||
else if (this->m_port > 0xFFFF)
|
||||
this->m_port = 0xFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -123,7 +123,9 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Settings::add("hex.builtin.setting.interface", "hex.builtin.setting.interface.fps", 60, [](auto name, nlohmann::json &setting) {
|
||||
static int fps = static_cast<int>(setting);
|
||||
|
||||
if (ImGui::SliderInt(name.data(), &fps, 15, 60)) {
|
||||
auto format = fps > 200 ? "hex.builtin.setting.interface.fps.unlocked"_lang : "%d FPS";
|
||||
|
||||
if (ImGui::SliderInt(name.data(), &fps, 15, 201, format, ImGuiSliderFlags_AlwaysClamp)) {
|
||||
setting = fps;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -30,13 +30,6 @@ namespace hex::plugin::builtin {
|
||||
using namespace std::literals::chrono_literals;
|
||||
using namespace hex::literals;
|
||||
|
||||
int updateStringSizeCallback(ImGuiInputTextCallbackData *data) {
|
||||
auto &mathInput = *static_cast<std::string*>(data->UserData);
|
||||
|
||||
mathInput.resize(data->BufTextLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drawDemangler() {
|
||||
static std::vector<char> mangledBuffer(0xF'FFFF, 0x00);
|
||||
static std::string demangledName;
|
||||
@@ -108,9 +101,9 @@ namespace hex::plugin::builtin {
|
||||
static auto replacePattern = []{ std::string s; s.reserve(0xFFF); return s; }();
|
||||
static auto regexOutput = []{ std::string s; s.reserve(0xFFF); return s; }();
|
||||
|
||||
bool changed1 = ImGui::InputText("hex.builtin.tools.regex_replacer.pattern"_lang, regexPattern.data(), regexPattern.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, ®exPattern);
|
||||
bool changed2 = ImGui::InputText("hex.builtin.tools.regex_replacer.replace"_lang, replacePattern.data(), replacePattern.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &replacePattern);
|
||||
bool changed3 = ImGui::InputTextMultiline("hex.builtin.tools.regex_replacer.input"_lang, regexInput.data(), regexInput.capacity(), ImVec2(0, 0), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, ®exInput);
|
||||
bool changed1 = ImGui::InputText("hex.builtin.tools.regex_replacer.pattern"_lang, regexPattern.data(), regexPattern.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, ®exPattern);
|
||||
bool changed2 = ImGui::InputText("hex.builtin.tools.regex_replacer.replace"_lang, replacePattern.data(), replacePattern.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &replacePattern);
|
||||
bool changed3 = ImGui::InputTextMultiline("hex.builtin.tools.regex_replacer.input"_lang, regexInput.data(), regexInput.capacity(), ImVec2(0, 0), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, ®exInput);
|
||||
|
||||
if (changed1 || changed2 || changed3) {
|
||||
try {
|
||||
@@ -363,7 +356,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth());
|
||||
if (ImGui::InputText("##input", mathInput.data(), mathInput.capacity(), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &mathInput)) {
|
||||
if (ImGui::InputText("##input", mathInput.data(), mathInput.capacity(), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &mathInput)) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
evaluate = true;
|
||||
}
|
||||
@@ -619,7 +612,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
bool startSearch;
|
||||
|
||||
startSearch = ImGui::InputText("##search", searchString.data(), searchString.capacity(), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &searchString);
|
||||
startSearch = ImGui::InputText("##search", searchString.data(), searchString.capacity(), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &searchString);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(searchProcess.valid() && searchProcess.wait_for(0s) != std::future_status::ready || searchString.empty());
|
||||
@@ -685,7 +678,7 @@ namespace hex::plugin::builtin {
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.input"_lang);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &selectedFile);
|
||||
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &selectedFile);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("...")) {
|
||||
hex::openFileBrowser("hex.builtin.tools.file_tools.shredder.picker"_lang, DialogMode::Open, {}, [](const std::string &path) {
|
||||
@@ -750,8 +743,9 @@ namespace hex::plugin::builtin {
|
||||
size_t fileSize = file.getSize();
|
||||
for (const auto &pattern : overwritePattern) {
|
||||
for (u64 offset = 0; offset < fileSize; offset += 3) {
|
||||
file.write(pattern.data(), std::min(pattern.size(), fileSize - offset));
|
||||
file.write(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
|
||||
}
|
||||
|
||||
file.flush();
|
||||
}
|
||||
|
||||
@@ -799,7 +793,7 @@ namespace hex::plugin::builtin {
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.tools.file_tools.splitter.input"_lang);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &selectedFile);
|
||||
ImGui::InputText("##path", selectedFile.data(), selectedFile.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &selectedFile);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("...##input")) {
|
||||
hex::openFileBrowser("hex.builtin.tools.file_tools.splitter.picker.input"_lang, DialogMode::Open, {}, [](const std::string &path) {
|
||||
@@ -809,7 +803,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.tools.file_tools.splitter.output"_lang);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##base_path", baseOutputPath.data(), baseOutputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &baseOutputPath);
|
||||
ImGui::InputText("##base_path", baseOutputPath.data(), baseOutputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &baseOutputPath);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("...##output")) {
|
||||
hex::openFileBrowser("hex.builtin.tools.file_tools.splitter.picker.output"_lang, DialogMode::Save, {}, [](const std::string &path) {
|
||||
@@ -956,7 +950,7 @@ namespace hex::plugin::builtin {
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.tools.file_tools.combiner.output"_lang);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##output_path", outputPath.data(), outputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, updateStringSizeCallback, &outputPath);
|
||||
ImGui::InputText("##output_path", outputPath.data(), outputPath.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &outputPath);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("...")) {
|
||||
hex::openFileBrowser("hex.builtin.tools.file_tools.combiner.output.picker"_lang, DialogMode::Save, {}, [](const std::string &path) {
|
||||
|
||||
@@ -13,6 +13,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void addFooterItems() {
|
||||
|
||||
if (hex::isProcessElevated()) {
|
||||
ContentRegistry::Interface::addFooterItem([] {
|
||||
ImGui::TextUnformatted(ICON_VS_SHIELD);
|
||||
});
|
||||
}
|
||||
|
||||
ContentRegistry::Interface::addFooterItem([] {
|
||||
static float framerate = 0;
|
||||
if (ImGui::HasSecondPassed()) {
|
||||
@@ -26,19 +32,17 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void addToolbarItems() {
|
||||
ContentRegistry::Interface::addToolbarItem([] {
|
||||
const static auto buttonSize = ImVec2(ImGui::GetCurrentWindow()->MenuBarHeight(), ImGui::GetCurrentWindow()->MenuBarHeight());
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
// Undo
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_DISCARD, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_DISCARD, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
provider->undo();
|
||||
}, !ImHexApi::Provider::isValid() || !provider->canUndo());
|
||||
|
||||
// Redo
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_REDO, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_REDO, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
provider->redo();
|
||||
}, !ImHexApi::Provider::isValid() || !provider->canRedo());
|
||||
|
||||
@@ -46,11 +50,11 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
|
||||
// Create new file
|
||||
if (ImGui::ToolBarButton(ICON_VS_FILE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGray), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_FILE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGray)))
|
||||
EventManager::post<RequestOpenWindow>("Create File");
|
||||
|
||||
// Open file
|
||||
if (ImGui::ToolBarButton(ICON_VS_FOLDER_OPENED, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBrown), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_FOLDER_OPENED, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBrown)))
|
||||
EventManager::post<RequestOpenWindow>("Open File");
|
||||
|
||||
|
||||
@@ -58,14 +62,14 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Save file
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
provider->save();
|
||||
}, !ImHexApi::Provider::isValid() || !provider->isWritable() || !provider->isSavable());
|
||||
|
||||
// Save file as
|
||||
ImGui::Disabled([&provider] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE_AS, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue), buttonSize))
|
||||
hex::openFileBrowser("hex.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [&provider](auto path) {
|
||||
if (ImGui::ToolBarButton(ICON_VS_SAVE_AS, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBlue)))
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [&provider](auto path) {
|
||||
provider->saveAs(path);
|
||||
});
|
||||
}, !ImHexApi::Provider::isValid() || !provider->isSavable());
|
||||
@@ -76,7 +80,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Create bookmark
|
||||
ImGui::Disabled([] {
|
||||
if (ImGui::ToolBarButton(ICON_VS_BOOKMARK, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen), buttonSize)) {
|
||||
if (ImGui::ToolBarButton(ICON_VS_BOOKMARK, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen))) {
|
||||
Region region = { 0 };
|
||||
EventManager::post<QuerySelection>(region);
|
||||
|
||||
|
||||
47
plugins/builtin/source/content/views.cpp
Normal file
47
plugins/builtin/source/content/views.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "content/views/view_hexeditor.hpp"
|
||||
#include "content/views/view_pattern_editor.hpp"
|
||||
#include "content/views/view_pattern_data.hpp"
|
||||
#include "content/views/view_hashes.hpp"
|
||||
#include "content/views/view_information.hpp"
|
||||
#include "content/views/view_help.hpp"
|
||||
#include "content/views/view_tools.hpp"
|
||||
#include "content/views/view_strings.hpp"
|
||||
#include "content/views/view_data_inspector.hpp"
|
||||
#include "content/views/view_disassembler.hpp"
|
||||
#include "content/views/view_bookmarks.hpp"
|
||||
#include "content/views/view_patches.hpp"
|
||||
#include "content/views/view_command_palette.hpp"
|
||||
#include "content/views/view_settings.hpp"
|
||||
#include "content/views/view_data_processor.hpp"
|
||||
#include "content/views/view_yara.hpp"
|
||||
#include "content/views/view_constants.hpp"
|
||||
#include "content/views/view_store.hpp"
|
||||
#include "content/views/view_diff.hpp"
|
||||
#include "content/views/view_provider_settings.hpp"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
void registerViews() {
|
||||
ContentRegistry::Views::add<ViewHexEditor>();
|
||||
ContentRegistry::Views::add<ViewPatternEditor>();
|
||||
ContentRegistry::Views::add<ViewPatternData>();
|
||||
ContentRegistry::Views::add<ViewDataInspector>();
|
||||
ContentRegistry::Views::add<ViewHashes>();
|
||||
ContentRegistry::Views::add<ViewInformation>();
|
||||
ContentRegistry::Views::add<ViewStrings>();
|
||||
ContentRegistry::Views::add<ViewDisassembler>();
|
||||
ContentRegistry::Views::add<ViewBookmarks>();
|
||||
ContentRegistry::Views::add<ViewPatches>();
|
||||
ContentRegistry::Views::add<ViewTools>();
|
||||
ContentRegistry::Views::add<ViewCommandPalette>();
|
||||
ContentRegistry::Views::add<ViewHelp>();
|
||||
ContentRegistry::Views::add<ViewSettings>();
|
||||
ContentRegistry::Views::add<ViewDataProcessor>();
|
||||
ContentRegistry::Views::add<ViewYara>();
|
||||
ContentRegistry::Views::add<ViewConstants>();
|
||||
ContentRegistry::Views::add<ViewStore>();
|
||||
ContentRegistry::Views::add<ViewDiff>();
|
||||
ContentRegistry::Views::add<ViewProviderSettings>();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +1,22 @@
|
||||
#include "views/view_bookmarks.hpp"
|
||||
#include "content/views/view_bookmarks.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include "helpers/project_file_handler.hpp"
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewBookmarks::ViewBookmarks() : View("hex.view.bookmarks.name") {
|
||||
ViewBookmarks::ViewBookmarks() : View("hex.builtin.view.bookmarks.name") {
|
||||
EventManager::subscribe<RequestAddBookmark>(this, [](ImHexApi::Bookmarks::Entry bookmark) {
|
||||
bookmark.comment.resize(0xF'FFFF);
|
||||
|
||||
if (bookmark.name.empty()) {
|
||||
bookmark.name.resize(64);
|
||||
std::memset(bookmark.name.data(), 0x00, 64);
|
||||
std::strcpy(bookmark.name.data(), hex::format("hex.view.bookmarks.default_title"_lang,
|
||||
std::strcpy(bookmark.name.data(), hex::format("hex.builtin.view.bookmarks.default_title"_lang,
|
||||
bookmark.region.address,
|
||||
bookmark.region.address + bookmark.region.size - 1).c_str());
|
||||
}
|
||||
@@ -37,22 +37,27 @@ namespace hex {
|
||||
EventManager::subscribe<EventProjectFileStore>(this, []{
|
||||
ProjectFile::setBookmarks(SharedData::bookmarkEntries);
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventFileUnloaded>(this, []{
|
||||
ImHexApi::Bookmarks::getEntries().clear();
|
||||
});
|
||||
}
|
||||
|
||||
ViewBookmarks::~ViewBookmarks() {
|
||||
EventManager::unsubscribe<RequestAddBookmark>(this);
|
||||
EventManager::unsubscribe<EventProjectFileLoad>(this);
|
||||
EventManager::unsubscribe<EventProjectFileStore>(this);
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
}
|
||||
|
||||
void ViewBookmarks::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.bookmarks.name").c_str(), &this->getWindowOpenState())) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.bookmarks.name").c_str(), &this->getWindowOpenState())) {
|
||||
if (ImGui::BeginChild("##scrolling")) {
|
||||
|
||||
auto &bookmarks = ImHexApi::Bookmarks::getEntries();
|
||||
|
||||
if (bookmarks.empty()) {
|
||||
std::string text = "hex.view.bookmarks.no_bookmarks"_lang;
|
||||
std::string text = "hex.builtin.view.bookmarks.no_bookmarks"_lang;
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str());
|
||||
auto availableSpace = ImGui::GetContentRegionAvail();
|
||||
|
||||
@@ -73,10 +78,10 @@ namespace hex {
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, u32(hoverColor));
|
||||
if (ImGui::CollapsingHeader(std::string(name.data()).c_str())) {
|
||||
ImGui::TextUnformatted("hex.view.bookmarks.title.info"_lang);
|
||||
if (ImGui::CollapsingHeader((std::string(name.data()) + "###bookmark").c_str())) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.bookmarks.title.info"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted(hex::format("hex.view.bookmarks.address"_lang, region.address, region.address + region.size - 1, region.size).c_str());
|
||||
ImGui::TextUnformatted(hex::format("hex.builtin.view.bookmarks.address"_lang, region.address, region.address + region.size - 1, region.size).c_str());
|
||||
|
||||
if (ImGui::BeginChild("hexData", ImVec2(0, ImGui::GetTextLineHeight() * 8), true)) {
|
||||
size_t offset = region.address % 0x10;
|
||||
@@ -123,11 +128,11 @@ namespace hex {
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::Button("hex.view.bookmarks.button.jump"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.bookmarks.button.jump"_lang))
|
||||
EventManager::post<RequestSelectionChange>(region);
|
||||
ImGui::SameLine(0, 15);
|
||||
|
||||
if (ImGui::Button("hex.view.bookmarks.button.remove"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.bookmarks.button.remove"_lang))
|
||||
bookmarkToRemove = iter;
|
||||
ImGui::SameLine(0, 15);
|
||||
|
||||
@@ -138,10 +143,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.view.bookmarks.header.name"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.bookmarks.header.name"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::ColorEdit4("hex.view.bookmarks.header.color"_lang, (float*)&headerColor.Value, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoAlpha | (locked ? ImGuiColorEditFlags_NoPicker : ImGuiColorEditFlags_None));
|
||||
ImGui::ColorEdit4("hex.builtin.view.bookmarks.header.color"_lang, (float*)&headerColor.Value, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoAlpha | (locked ? ImGuiColorEditFlags_NoPicker : ImGuiColorEditFlags_None));
|
||||
color = headerColor;
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -151,7 +156,7 @@ namespace hex {
|
||||
ImGui::InputText("##nameInput", name.data(), 64);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.view.bookmarks.header.comment"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.bookmarks.header.comment"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
if (locked)
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "views/view_command_palette.hpp"
|
||||
#include "content/views/view_command_palette.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewCommandPalette::ViewCommandPalette() : View("hex.view.command_palette.name") {
|
||||
ViewCommandPalette::ViewCommandPalette() : View("hex.builtin.view.command_palette.name") {
|
||||
this->m_commandBuffer.resize(1024, 0x00);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace hex {
|
||||
if (!this->m_commandPaletteOpen) return;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(SharedData::windowPos.x + SharedData::windowSize.x * 0.5F, SharedData::windowPos.y), ImGuiCond_Always, ImVec2(0.5F,0.0F));
|
||||
if (ImGui::BeginPopup("hex.view.command_palette.name"_lang)) {
|
||||
if (ImGui::BeginPopup("hex.builtin.view.command_palette.name"_lang)) {
|
||||
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
@@ -45,6 +45,11 @@ namespace hex {
|
||||
}
|
||||
|
||||
if (this->m_focusInputTextBox) {
|
||||
auto textState = ImGui::GetInputTextState(ImGui::GetID("##command_input"));
|
||||
if (textState != nullptr) {
|
||||
textState->Stb.cursor = strlen(this->m_commandBuffer.data());
|
||||
}
|
||||
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
this->m_focusInputTextBox = false;
|
||||
}
|
||||
@@ -70,7 +75,7 @@ namespace hex {
|
||||
bool ViewCommandPalette::handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt) {
|
||||
if (ctrl && shift && keys['P']) {
|
||||
View::doLater([this] {
|
||||
ImGui::OpenPopup("hex.view.command_palette.name"_lang);
|
||||
ImGui::OpenPopup("hex.builtin.view.command_palette.name"_lang);
|
||||
this->m_commandPaletteOpen = true;
|
||||
this->m_justOpened = true;
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_constants.hpp"
|
||||
#include "content/views/view_constants.hpp"
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
@@ -8,9 +8,9 @@
|
||||
#include <filesystem>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewConstants::ViewConstants() : View("hex.view.constants.name") {
|
||||
ViewConstants::ViewConstants() : View("hex.builtin.view.constants.name") {
|
||||
this->reloadConstants();
|
||||
|
||||
this->m_filter.reserve(0xFFFF);
|
||||
@@ -65,7 +65,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewConstants::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.constants.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.constants.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
|
||||
ImGui::InputText("##search", this->m_filter.data(), this->m_filter.capacity(), ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) {
|
||||
auto &view = *static_cast<ViewConstants*>(data->UserData);
|
||||
@@ -88,10 +88,10 @@ namespace hex {
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
||||
ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.constants.row.category"_lang, 0, -1, ImGui::GetID("category"));
|
||||
ImGui::TableSetupColumn("hex.view.constants.row.name"_lang, 0, -1, ImGui::GetID("name"));
|
||||
ImGui::TableSetupColumn("hex.view.constants.row.desc"_lang, 0, -1, ImGui::GetID("desc"));
|
||||
ImGui::TableSetupColumn("hex.view.constants.row.value"_lang, 0, -1, ImGui::GetID("value"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.constants.row.category"_lang, 0, -1, ImGui::GetID("category"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.constants.row.name"_lang, 0, -1, ImGui::GetID("name"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.constants.row.desc"_lang, 0, -1, ImGui::GetID("desc"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.constants.row.value"_lang, 0, -1, ImGui::GetID("value"));
|
||||
|
||||
auto sortSpecs = ImGui::TableGetSortSpecs();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_data_inspector.hpp"
|
||||
#include "content/views/view_data_inspector.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
extern int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end);
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using NumberDisplayStyle = ContentRegistry::DataInspector::NumberDisplayStyle;
|
||||
|
||||
ViewDataInspector::ViewDataInspector() : View("hex.view.data_inspector.name") {
|
||||
ViewDataInspector::ViewDataInspector() : View("hex.builtin.view.data_inspector.name") {
|
||||
EventManager::subscribe<EventRegionSelected>(this, [this](Region region) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.data_inspector.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.data_inspector.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable() && this->m_validBytes > 0) {
|
||||
@@ -55,8 +55,8 @@ namespace hex {
|
||||
ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg,
|
||||
ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * (this->m_cachedData.size() + 1)))) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.data_inspector.table.name"_lang);
|
||||
ImGui::TableSetupColumn("hex.view.data_inspector.table.value"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.data_inspector.table.name"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.data_inspector.table.value"_lang);
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace hex {
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
} else {
|
||||
std::string text = "hex.view.data_inspector.no_data"_lang;
|
||||
std::string text = "hex.builtin.view.data_inspector.no_data"_lang;
|
||||
auto textSize = ImGui::CalcTextSize(text.c_str());
|
||||
auto availableSpace = ImGui::GetContentRegionAvail();
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#include "views/view_data_processor.hpp"
|
||||
#include "content/views/view_data_processor.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <helpers/project_file_handler.hpp>
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
|
||||
#include <imnodes.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewDataProcessor::ViewDataProcessor() : View("hex.view.data_processor.name") {
|
||||
ViewDataProcessor::ViewDataProcessor() : View("hex.builtin.view.data_processor.name") {
|
||||
EventManager::subscribe<RequestChangeTheme>(this, [](u32 theme) {
|
||||
switch (theme) {
|
||||
default:
|
||||
@@ -31,7 +31,11 @@ namespace hex {
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventProjectFileLoad>(this, [this] {
|
||||
this->loadNodes(ProjectFile::getDataProcessorContent());
|
||||
try {
|
||||
this->loadNodes(ProjectFile::getDataProcessorContent());
|
||||
} catch (nlohmann::json::exception &e) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventFileLoaded>(this, [this](const std::string &path){
|
||||
@@ -138,7 +142,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewDataProcessor::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.data_processor.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.data_processor.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) {
|
||||
ImNodes::ClearNodeSelection();
|
||||
@@ -158,7 +162,7 @@ namespace hex {
|
||||
dp::Node *node = nullptr;
|
||||
|
||||
if (ImNodes::NumSelectedNodes() > 0 || ImNodes::NumSelectedLinks() > 0) {
|
||||
if (ImGui::MenuItem("hex.view.data_processor.name"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.data_processor.name"_lang)) {
|
||||
std::vector<int> ids;
|
||||
ids.resize(ImNodes::NumSelectedNodes());
|
||||
ImNodes::GetSelectedNodes(ids.data());
|
||||
@@ -217,14 +221,14 @@ namespace hex {
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("Node Menu")) {
|
||||
if (ImGui::MenuItem("hex.view.data_processor.menu.remove_node"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.data_processor.menu.remove_node"_lang))
|
||||
this->eraseNodes({ this->m_rightClickedId });
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("Link Menu")) {
|
||||
if (ImGui::MenuItem("hex.view.data_processor.menu.remove_link"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.data_processor.menu.remove_link"_lang))
|
||||
this->eraseLink(this->m_rightClickedId);
|
||||
|
||||
ImGui::EndPopup();
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_diff.hpp"
|
||||
#include "content/views/view_diff.hpp"
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
@@ -8,27 +8,30 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewDiff::ViewDiff() : View("hex.view.diff.name") {
|
||||
ViewDiff::ViewDiff() : View("hex.builtin.view.diff.name") {
|
||||
|
||||
EventManager::subscribe<EventSettingsChanged>(this, [this]{
|
||||
{
|
||||
auto columnCount = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.column_count");
|
||||
|
||||
this->m_columnCount = static_cast<int>(columnCount);
|
||||
if (columnCount.is_number())
|
||||
this->m_columnCount = static_cast<int>(columnCount);
|
||||
}
|
||||
|
||||
{
|
||||
auto greyOutZeros = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.grey_zeros");
|
||||
|
||||
this->m_greyedOutZeros = static_cast<int>(greyOutZeros);
|
||||
if (greyOutZeros.is_number())
|
||||
this->m_greyedOutZeros = static_cast<int>(greyOutZeros);
|
||||
}
|
||||
|
||||
{
|
||||
auto upperCaseHex = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.uppercase_hex");
|
||||
|
||||
this->m_upperCaseHex = static_cast<int>(upperCaseHex);
|
||||
if (upperCaseHex.is_number())
|
||||
this->m_upperCaseHex = static_cast<int>(upperCaseHex);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -158,7 +161,7 @@ namespace hex {
|
||||
lastHighlightEnd.reset();
|
||||
}
|
||||
|
||||
ImGui::SameLine(0.0F, col % 8 == 7 ? glyphWidth * 2.5F : glyphWidth * 0.25F);
|
||||
ImGui::SameLine(0.0F, col % 8 == 7 ? glyphWidth * 2.5F : glyphWidth * 0.5F);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
@@ -166,7 +169,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewDiff::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.diff.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.diff.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(1);
|
||||
@@ -198,7 +201,7 @@ namespace hex {
|
||||
for (u8 i = 0; i < 2; i++) {
|
||||
for (u8 col = 0; col < this->m_columnCount; col++) {
|
||||
ImGui::TextUnformatted(hex::format(this->m_upperCaseHex ? "{:02X}" : "{:02x}", col).c_str());
|
||||
ImGui::SameLine(0.0F, col % 8 == 7 ? glyphWidth * 2.5F : glyphWidth * 0.25F);
|
||||
ImGui::SameLine(0.0F, col % 8 == 7 ? glyphWidth * 2.5F : glyphWidth * 0.5F);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
@@ -208,7 +211,7 @@ namespace hex {
|
||||
if (this->m_providerA >= 0 && this->m_providerB >= 0) {
|
||||
auto &providers = ImHexApi::Provider::getProviders();
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(std::max(providers[this->m_providerA]->getSize() / this->m_columnCount, providers[this->m_providerB]->getSize() / this->m_columnCount));
|
||||
clipper.Begin(std::max(providers[this->m_providerA]->getSize() / this->m_columnCount, providers[this->m_providerB]->getSize() / this->m_columnCount) + 1, ImGui::GetTextLineHeightWithSpacing());
|
||||
|
||||
// Draw diff lines
|
||||
while (clipper.Step()) {
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_disassembler.hpp"
|
||||
#include "content/views/view_disassembler.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewDisassembler::ViewDisassembler() : View("hex.view.disassembler.name") {
|
||||
ViewDisassembler::ViewDisassembler() : View("hex.builtin.view.disassembler.name") {
|
||||
EventManager::subscribe<EventDataChanged>(this, [this]() {
|
||||
this->disassemble();
|
||||
});
|
||||
@@ -27,11 +27,16 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventFileUnloaded>(this, [this]{
|
||||
this->m_disassembly.clear();
|
||||
});
|
||||
}
|
||||
|
||||
ViewDisassembler::~ViewDisassembler() {
|
||||
EventManager::unsubscribe<EventDataChanged>(this);
|
||||
EventManager::unsubscribe<EventRegionSelected>(this);
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
}
|
||||
|
||||
void ViewDisassembler::disassemble() {
|
||||
@@ -104,15 +109,15 @@ namespace hex {
|
||||
|
||||
void ViewDisassembler::drawContent() {
|
||||
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.disassembler.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.disassembler.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
ImGui::TextUnformatted("hex.view.disassembler.position"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.disassembler.position"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::InputScalar("hex.view.disassembler.base"_lang, ImGuiDataType_U64, &this->m_baseAddress, nullptr, nullptr, "%08llX", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::InputScalarN("hex.view.disassembler.region"_lang, ImGuiDataType_U64, this->m_codeRegion, 2, nullptr, nullptr, "%08llX", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::InputScalar("hex.builtin.view.disassembler.base"_lang, ImGuiDataType_U64, &this->m_baseAddress, nullptr, nullptr, "%08llX", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::InputScalarN("hex.builtin.view.disassembler.region"_lang, ImGuiDataType_U64, this->m_codeRegion, 2, nullptr, nullptr, "%08llX", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
ImGui::Checkbox("hex.common.match_selection"_lang, &this->m_shouldMatchSelection);
|
||||
if (ImGui::IsItemEdited()) {
|
||||
@@ -121,10 +126,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.view.disassembler.settings.header"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.disassembler.settings.header"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Combo("hex.view.disassembler.arch"_lang, reinterpret_cast<int*>(&this->m_architecture), Disassembler::ArchitectureNames, Disassembler::getArchitectureSupportedCount());
|
||||
ImGui::Combo("hex.builtin.view.disassembler.arch"_lang, reinterpret_cast<int*>(&this->m_architecture), Disassembler::ArchitectureNames, Disassembler::getArchitectureSupportedCount());
|
||||
|
||||
|
||||
if (ImGui::BeginChild("modes", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 6), true, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
@@ -148,19 +153,19 @@ namespace hex {
|
||||
if (this->m_modeBasicARM == cs_mode(0))
|
||||
this->m_modeBasicARM = CS_MODE_ARM;
|
||||
|
||||
if (ImGui::RadioButton("hex.view.disassembler.arm.arm"_lang, this->m_modeBasicARM == CS_MODE_ARM))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.arm.arm"_lang, this->m_modeBasicARM == CS_MODE_ARM))
|
||||
this->m_modeBasicARM = CS_MODE_ARM;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.arm.thumb"_lang, this->m_modeBasicARM == CS_MODE_THUMB))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.arm.thumb"_lang, this->m_modeBasicARM == CS_MODE_THUMB))
|
||||
this->m_modeBasicARM = CS_MODE_THUMB;
|
||||
|
||||
if (ImGui::RadioButton("hex.view.disassembler.arm.default"_lang, (this->m_modeExtraARM & (CS_MODE_MCLASS | CS_MODE_V8)) == 0))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.arm.default"_lang, (this->m_modeExtraARM & (CS_MODE_MCLASS | CS_MODE_V8)) == 0))
|
||||
this->m_modeExtraARM = cs_mode(0);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.arm.cortex_m"_lang, (this->m_modeExtraARM & (CS_MODE_MCLASS | CS_MODE_V8)) == CS_MODE_MCLASS))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.arm.cortex_m"_lang, (this->m_modeExtraARM & (CS_MODE_MCLASS | CS_MODE_V8)) == CS_MODE_MCLASS))
|
||||
this->m_modeExtraARM = CS_MODE_MCLASS;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.arm.armv8"_lang, (this->m_modeExtraARM & (CS_MODE_MCLASS | CS_MODE_V8)) == CS_MODE_V8))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.arm.armv8"_lang, (this->m_modeExtraARM & (CS_MODE_MCLASS | CS_MODE_V8)) == CS_MODE_V8))
|
||||
this->m_modeExtraARM = CS_MODE_V8;
|
||||
break;
|
||||
case Architecture::MIPS:
|
||||
@@ -173,16 +178,16 @@ namespace hex {
|
||||
if (this->m_modeBasicMIPS == cs_mode(0))
|
||||
this->m_modeBasicMIPS = CS_MODE_MIPS32;
|
||||
|
||||
if (ImGui::RadioButton("hex.view.disassembler.mips.mips32"_lang, this->m_modeBasicMIPS == CS_MODE_MIPS32))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips32"_lang, this->m_modeBasicMIPS == CS_MODE_MIPS32))
|
||||
this->m_modeBasicMIPS = CS_MODE_MIPS32;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.mips.mips64"_lang, this->m_modeBasicMIPS == CS_MODE_MIPS64))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips64"_lang, this->m_modeBasicMIPS == CS_MODE_MIPS64))
|
||||
this->m_modeBasicMIPS = CS_MODE_MIPS64;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.mips.mips32R6"_lang, this->m_modeBasicMIPS == CS_MODE_MIPS32R6))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.mips.mips32R6"_lang, this->m_modeBasicMIPS == CS_MODE_MIPS32R6))
|
||||
this->m_modeBasicMIPS = CS_MODE_MIPS32R6;
|
||||
|
||||
ImGui::Checkbox("hex.view.disassembler.mips.micro"_lang, &this->m_micoMode);
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.mips.micro"_lang, &this->m_micoMode);
|
||||
break;
|
||||
case Architecture::X86:
|
||||
this->m_modeBasicARM = cs_mode(0);
|
||||
@@ -195,13 +200,13 @@ namespace hex {
|
||||
if (this->m_modeBasicX86 == cs_mode(0))
|
||||
this->m_modeBasicX86 = CS_MODE_16;
|
||||
|
||||
if (ImGui::RadioButton("hex.view.disassembler.x86.16bit"_lang, this->m_modeBasicX86 == CS_MODE_16))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.x86.16bit"_lang, this->m_modeBasicX86 == CS_MODE_16))
|
||||
this->m_modeBasicX86 = CS_MODE_16;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.x86.32bit"_lang, this->m_modeBasicX86 == CS_MODE_32))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.x86.32bit"_lang, this->m_modeBasicX86 == CS_MODE_32))
|
||||
this->m_modeBasicX86 = CS_MODE_32;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.x86.64bit"_lang, this->m_modeBasicX86 == CS_MODE_64))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.x86.64bit"_lang, this->m_modeBasicX86 == CS_MODE_64))
|
||||
this->m_modeBasicX86 = CS_MODE_64;
|
||||
break;
|
||||
case Architecture::PPC:
|
||||
@@ -215,10 +220,10 @@ namespace hex {
|
||||
if (m_modeBasicPPC == cs_mode(0))
|
||||
this->m_modeBasicPPC = CS_MODE_32;
|
||||
|
||||
if (ImGui::RadioButton("hex.view.disassembler.ppc.32bit"_lang, this->m_modeBasicPPC == CS_MODE_32))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.ppc.32bit"_lang, this->m_modeBasicPPC == CS_MODE_32))
|
||||
this->m_modeBasicPPC = CS_MODE_32;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("hex.view.disassembler.ppc.64bit"_lang, this->m_modeBasicPPC == CS_MODE_64))
|
||||
if (ImGui::RadioButton("hex.builtin.view.disassembler.ppc.64bit"_lang, this->m_modeBasicPPC == CS_MODE_64))
|
||||
this->m_modeBasicPPC = CS_MODE_64;
|
||||
break;
|
||||
case Architecture::SPARC:
|
||||
@@ -229,7 +234,7 @@ namespace hex {
|
||||
this->m_modeBasicPPC = cs_mode(0);
|
||||
this->m_micoMode = false;
|
||||
|
||||
ImGui::Checkbox("hex.view.disassembler.sparc.v9"_lang, &this->m_sparcV9Mode);
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.sparc.v9"_lang, &this->m_sparcV9Mode);
|
||||
break;
|
||||
case Architecture::ARM64:
|
||||
case Architecture::SYSZ:
|
||||
@@ -252,26 +257,26 @@ namespace hex {
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Disabled([this] {
|
||||
if (ImGui::Button("hex.view.disassembler.disassemble"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.disassembler.disassemble"_lang))
|
||||
this->disassemble();
|
||||
}, this->m_disassembling);
|
||||
|
||||
if (this->m_disassembling) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextSpinner("hex.view.disassembler.disassembling"_lang);
|
||||
ImGui::TextSpinner("hex.builtin.view.disassembler.disassembling"_lang);
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::TextUnformatted("hex.view.disassembler.disassembly.title"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.disassembler.disassembly.title"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginTable("##disassembly", 4, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_Reorderable)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.disassembler.disassembly.address"_lang);
|
||||
ImGui::TableSetupColumn("hex.view.disassembler.disassembly.offset"_lang);
|
||||
ImGui::TableSetupColumn("hex.view.disassembler.disassembly.bytes"_lang);
|
||||
ImGui::TableSetupColumn("hex.view.disassembler.disassembly.title"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.address"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.offset"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_disassembly.size());
|
||||
307
plugins/builtin/source/content/views/view_hashes.cpp
Normal file
307
plugins/builtin/source/content/views/view_hashes.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
#include "content/views/view_hashes.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewHashes::ViewHashes() : View("hex.builtin.view.hashes.name") {
|
||||
EventManager::subscribe<EventDataChanged>(this, [this]() {
|
||||
this->m_shouldInvalidate = true;
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventRegionSelected>(this, [this](Region region) {
|
||||
if (this->m_shouldMatchSelection) {
|
||||
if (region.address == size_t(-1)) {
|
||||
this->m_hashRegion[0] = this->m_hashRegion[1] = 0;
|
||||
} else {
|
||||
this->m_hashRegion[0] = region.address;
|
||||
this->m_hashRegion[1] = region.size + 1; //WARNING: get size - 1 as region size
|
||||
}
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ViewHashes::~ViewHashes() {
|
||||
EventManager::unsubscribe<EventDataChanged>(this);
|
||||
EventManager::unsubscribe<EventRegionSelected>(this);
|
||||
}
|
||||
|
||||
|
||||
template<size_t Size>
|
||||
static void formatBigHexInt(std::array<u8, Size> dataArray, char *buffer, size_t bufferSize) {
|
||||
for (int i = 0; i < dataArray.size(); i++)
|
||||
snprintf(buffer + 2 * i, bufferSize - 2 * i, "%02X", dataArray[i]);
|
||||
}
|
||||
|
||||
void ViewHashes::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.hashes.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav)) {
|
||||
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isAvailable()) {
|
||||
|
||||
ImGui::TextUnformatted("hex.common.region"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::InputScalarN("##nolabel", ImGuiDataType_U64, this->m_hashRegion, 2, nullptr, nullptr, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.match_selection"_lang, &this->m_shouldMatchSelection);
|
||||
if (ImGui::IsItemEdited()) {
|
||||
// Force execution of Region Selection Event
|
||||
EventManager::post<RequestSelectionChange>(Region{ 0, 0 });
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.settings"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginCombo("hex.builtin.view.hashes.function"_lang, hashFunctionNames[this->m_currHashFunction].second, 0))
|
||||
{
|
||||
for (int i = 0; i < hashFunctionNames.size(); i++)
|
||||
{
|
||||
bool is_selected = (this->m_currHashFunction == i);
|
||||
if (ImGui::Selectable(hashFunctionNames[i].second, is_selected))
|
||||
this->m_currHashFunction = i;
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
this->m_shouldInvalidate = true;
|
||||
}
|
||||
|
||||
size_t dataSize = provider->getSize();
|
||||
if (this->m_hashRegion[1] >= provider->getBaseAddress() + dataSize)
|
||||
this->m_hashRegion[1] = provider->getBaseAddress() + dataSize;
|
||||
|
||||
|
||||
switch (hashFunctionNames[this->m_currHashFunction].first) {
|
||||
case HashFunctions::Crc8:
|
||||
{
|
||||
static int polynomial = 0x07, init = 0x0000, xorout = 0x0000;
|
||||
static bool reflectIn = false, reflectOut = false;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.reflectIn"_lang, &reflectIn);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.reflectOut"_lang, &reflectOut);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
static u8 result = 0;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::crc8(provider, this->m_hashRegion[0], this->m_hashRegion[1],
|
||||
polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%02X", result);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Crc16:
|
||||
{
|
||||
static int polynomial = 0x8005, init = 0x0000, xorout = 0x0000;
|
||||
static bool reflectIn = false, reflectOut = false;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.reflectIn"_lang, &reflectIn);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.reflectOut"_lang, &reflectOut);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
static u16 result = 0;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::crc16(provider, this->m_hashRegion[0], this->m_hashRegion[1],
|
||||
polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%04X", result);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Crc32:
|
||||
{
|
||||
static int polynomial = 0x04C11DB7, init = 0xFFFFFFFF, xorout = 0xFFFFFFFF;
|
||||
static bool reflectIn = true, reflectOut = true;
|
||||
|
||||
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.iv"_lang, &init, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.xorout"_lang, &xorout, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.reflectIn"_lang, &reflectIn);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::Checkbox("hex.common.reflectOut"_lang, &reflectOut);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.hashes.poly"_lang, &polynomial, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
if (ImGui::IsItemEdited()) this->m_shouldInvalidate = true;
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
static u32 result = 0;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::crc32(provider, this->m_hashRegion[0], this->m_hashRegion[1],
|
||||
polynomial, init, xorout, reflectIn, reflectOut);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%08X", result);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Md5:
|
||||
{
|
||||
static std::array<u8, 16> result = { 0 };
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::md5(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha1:
|
||||
{
|
||||
static std::array<u8, 20> result = { 0 };
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha1(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha224:
|
||||
{
|
||||
static std::array<u8, 28> result = { 0 };
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha224(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha256:
|
||||
{
|
||||
static std::array<u8, 32> result;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha256(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha384:
|
||||
{
|
||||
static std::array<u8, 48> result;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha384(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
case HashFunctions::Sha512:
|
||||
{
|
||||
static std::array<u8, 64> result;
|
||||
|
||||
if (this->m_shouldInvalidate)
|
||||
result = crypt::sha512(provider, this->m_hashRegion[0], this->m_hashRegion[1]);
|
||||
|
||||
char buffer[sizeof(result) * 2 + 1];
|
||||
formatBigHexInt(result, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.hashes.result"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::InputText("##nolabel", buffer, ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this->m_shouldInvalidate = false;
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ViewHashes::drawMenu() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
178
plugins/builtin/source/content/views/view_help.cpp
Normal file
178
plugins/builtin/source/content/views/view_help.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "content/views/view_help.hpp"
|
||||
#include <hex/helpers/paths.hpp>
|
||||
|
||||
#include <imgui_imhex_extensions.h>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewHelp::ViewHelp() : View("hex.builtin.view.help.about.name") {
|
||||
}
|
||||
|
||||
ViewHelp::~ViewHelp() {
|
||||
|
||||
}
|
||||
|
||||
static void link(const std::string &label, const std::string &url) {
|
||||
if (ImGui::BulletHyperlink(label.data()))
|
||||
hex::openWebpage(url.data());
|
||||
}
|
||||
|
||||
void ViewHelp::drawAboutMainPage() {
|
||||
ImGui::Text("ImHex Hex Editor v%s by WerWolv - " ICON_FA_CODE_BRANCH, IMHEX_VERSION);
|
||||
|
||||
#if defined(GIT_BRANCH) && defined(GIT_COMMIT_HASH)
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Hyperlink(hex::format("{0}@{1}", GIT_BRANCH, GIT_COMMIT_HASH).c_str()))
|
||||
hex::openWebpage("https://github.com/WerWolv/ImHex/commit/" GIT_COMMIT_HASH);
|
||||
#endif
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.help.about.translator"_lang);
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.help.about.source"_lang); ImGui::SameLine();
|
||||
if (ImGui::Hyperlink("WerWolv/ImHex"))
|
||||
hex::openWebpage("https://github.com/WerWolv/ImHex");
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::TextUnformatted("hex.builtin.view.help.about.donations"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
constexpr const char* Links[] = { "https://werwolv.net/donate", "https://www.patreon.com/werwolv", "https://github.com/sponsors/WerWolv" };
|
||||
|
||||
ImGui::TextWrapped("%s", static_cast<const char *>("hex.builtin.view.help.about.thanks"_lang));
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
for (auto &link : Links) {
|
||||
if (ImGui::Hyperlink(link))
|
||||
hex::openWebpage(link);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewHelp::drawContributorPage() {
|
||||
link("Mary for porting ImHex to MacOS", "https://github.com/Thog");
|
||||
link("Roblabla for adding the MSI Windows installer", "https://github.com/roblabla");
|
||||
link("jam1garner for adding support for Rust plugins", "https://github.com/jam1garner");
|
||||
|
||||
}
|
||||
|
||||
void ViewHelp::drawLibraryCreditsPage() {
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.2F, 0.2F, 0.2F, 0.3F));
|
||||
|
||||
link("ImGui by ocornut", "https://github.com/ocornut/imgui");
|
||||
link("imgui_club by ocornut", "https://github.com/ocornut/imgui_club");
|
||||
link("imnodes by Nelarius", "https://github.com/Nelarius/imnodes");
|
||||
link("ImGuiColorTextEdit by BalazsJako", "https://github.com/BalazsJako/ImGuiColorTextEdit");
|
||||
link("ImPlot by epezent", "https://github.com/epezent/implot");
|
||||
link("capstone by aquynh", "https://github.com/aquynh/capstone");
|
||||
link("JSON for Modern C++ by nlohmann", "https://github.com/nlohmann/json");
|
||||
link("YARA by VirusTotal", "https://github.com/VirusTotal/yara");
|
||||
link("Native File Dialog Extended by btzy and mlabbe", "https://github.com/btzy/nativefiledialog-extended");
|
||||
link("Native File Dialog Extended by btzy and mlabbe", "https://github.com/btzy/nativefiledialog-extended");
|
||||
ImGui::NewLine();
|
||||
link("GNU libmagic", "http://www.darwinsys.com/file/");
|
||||
link("GLFW3", "https://github.com/glfw/glfw");
|
||||
link("LLVM", "https://github.com/llvm/llvm-project");
|
||||
link("Python 3", "https://github.com/python/cpython");
|
||||
link("FreeType", "https://gitlab.freedesktop.org/freetype/freetype");
|
||||
link("Mbed TLS", "https://github.com/ARMmbed/mbedtls");
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
void ViewHelp::drawPathsPage() {
|
||||
if (ImGui::BeginTable("##imhex_paths", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("Type");
|
||||
ImGui::TableSetupColumn("Paths");
|
||||
|
||||
constexpr std::array<std::pair<const char*, ImHexPath>, 8> PathTypes = {{
|
||||
{ "Resources", ImHexPath::Resources },
|
||||
{ "Config", ImHexPath::Config },
|
||||
{ "Magic", ImHexPath::Magic },
|
||||
{ "Patterns", ImHexPath::Patterns },
|
||||
{ "Patterns Includes", ImHexPath::PatternsInclude },
|
||||
{ "Plugins", ImHexPath::Plugins },
|
||||
{ "Python Scripts", ImHexPath::Python },
|
||||
{ "Yara Patterns", ImHexPath::Yara }
|
||||
}};
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
for (const auto &[name, type] : PathTypes) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(name);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
for (auto &path : hex::getPath(type))
|
||||
ImGui::TextUnformatted(path.c_str());
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewHelp::drawAboutPopup() {
|
||||
ImGui::SetNextWindowSize(ImVec2(600, 350) * SharedData::globalScale, ImGuiCond_Always);
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.help.about.name").c_str(), &this->m_aboutWindowOpen, ImGuiWindowFlags_NoResize)) {
|
||||
|
||||
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
if (ImGui::BeginTabBar("about_tab_bar")) {
|
||||
|
||||
if (ImGui::BeginTabItem("ImHex")) {
|
||||
ImGui::NewLine();
|
||||
this->drawAboutMainPage();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.help.about.contributor"_lang)) {
|
||||
ImGui::NewLine();
|
||||
this->drawContributorPage();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.help.about.libs"_lang)) {
|
||||
ImGui::NewLine();
|
||||
this->drawLibraryCreditsPage();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.help.about.paths"_lang)) {
|
||||
ImGui::NewLine();
|
||||
this->drawPathsPage();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewHelp::drawContent() {
|
||||
if (!this->m_aboutWindowOpen)
|
||||
this->getWindowOpenState() = false;
|
||||
|
||||
this->drawAboutPopup();
|
||||
}
|
||||
|
||||
void ViewHelp::drawMenu() {
|
||||
if (ImGui::BeginMenu("hex.menu.help"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.help.about.name"_lang, "")) {
|
||||
View::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
|
||||
this->m_aboutWindowOpen = true;
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
if (ImGui::MenuItem("hex.builtin.view.help.documentation"_lang, "")) {
|
||||
hex::openWebpage("https://imhex.werwolv.net/docs");
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_hexeditor.hpp"
|
||||
#include "content/views/view_hexeditor.hpp"
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
@@ -6,10 +6,11 @@
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/pattern_language/pattern_data.hpp>
|
||||
|
||||
#include "providers/file_provider.hpp"
|
||||
#include "helpers/patches.hpp"
|
||||
#include "helpers/project_file_handler.hpp"
|
||||
#include "helpers/loader_script_handler.hpp"
|
||||
#include "content/providers/file_provider.hpp"
|
||||
|
||||
#include <hex/helpers/patches.hpp>
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
#include <hex/helpers/loader_script_handler.hpp>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
@@ -27,9 +28,9 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewHexEditor::ViewHexEditor() : View("hex.view.hexeditor.name"_lang) {
|
||||
ViewHexEditor::ViewHexEditor() : View("hex.builtin.view.hexeditor.name"_lang) {
|
||||
|
||||
this->m_searchStringBuffer.resize(0xFFF, 0x00);
|
||||
this->m_searchHexBuffer.resize(0xFFF, 0x00);
|
||||
@@ -40,7 +41,7 @@ namespace hex {
|
||||
return 0x00;
|
||||
|
||||
ImU8 byte;
|
||||
provider->readRelative(off, &byte, sizeof(ImU8));
|
||||
provider->read(off + provider->getBaseAddress() + provider->getCurrentPageAddress(), &byte, sizeof(ImU8));
|
||||
|
||||
return byte;
|
||||
};
|
||||
@@ -50,7 +51,7 @@ namespace hex {
|
||||
if (!provider->isAvailable() || !provider->isWritable())
|
||||
return;
|
||||
|
||||
provider->writeRelative(off, &d, sizeof(ImU8));
|
||||
provider->write(off + provider->getBaseAddress() + provider->getCurrentPageAddress(), &d, sizeof(ImU8));
|
||||
EventManager::post<EventDataChanged>();
|
||||
ProjectFile::markDirty();
|
||||
};
|
||||
@@ -60,7 +61,9 @@ namespace hex {
|
||||
|
||||
std::optional<u32> currColor, prevColor;
|
||||
|
||||
off += ImHexApi::Provider::get()->getBaseAddress();
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
off += provider->getBaseAddress() + provider->getCurrentPageAddress();
|
||||
|
||||
u32 alpha = static_cast<u32>(_this->m_highlightAlpha) << 24;
|
||||
|
||||
@@ -124,7 +127,7 @@ namespace hex {
|
||||
size_t size = std::min<size_t>(_this->m_currEncodingFile.getLongestSequence(), provider->getActualSize() - addr);
|
||||
|
||||
std::vector<u8> buffer(size);
|
||||
provider->readRelative(addr, buffer.data(), size);
|
||||
provider->read(addr + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), size);
|
||||
|
||||
auto [decoded, advance] = _this->m_currEncodingFile.getEncodingFor(buffer);
|
||||
|
||||
@@ -152,8 +155,8 @@ namespace hex {
|
||||
|
||||
if (region.size != 0) {
|
||||
provider->setCurrentPage(page.value());
|
||||
u64 start = region.address;
|
||||
this->m_memoryEditor.GotoAddrAndSelect(start - provider->getBaseAddress(), start + region.size - provider->getBaseAddress() - 1);
|
||||
u64 start = region.address - provider->getBaseAddress() - provider->getCurrentPageAddress();
|
||||
this->m_memoryEditor.GotoAddrAndSelect(start, start + region.size - 1);
|
||||
}
|
||||
|
||||
EventManager::post<EventRegionSelected>(Region { this->m_memoryEditor.DataPreviewAddr, (this->m_memoryEditor.DataPreviewAddrEnd - this->m_memoryEditor.DataPreviewAddr) + 1});
|
||||
@@ -166,7 +169,7 @@ namespace hex {
|
||||
EventManager::subscribe<EventWindowClosing>(this, [](GLFWwindow *window) {
|
||||
if (ProjectFile::hasUnsavedChanges()) {
|
||||
glfwSetWindowShouldClose(window, GLFW_FALSE);
|
||||
View::doLater([] { ImGui::OpenPopup("hex.view.hexeditor.exit_application.title"_lang); });
|
||||
View::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.exit_application.title"_lang); });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -180,9 +183,9 @@ namespace hex {
|
||||
|
||||
EventManager::subscribe<RequestOpenWindow>(this, [this](std::string name) {
|
||||
if (name == "Create File") {
|
||||
hex::openFileBrowser("hex.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
if (!this->createFile(path)) {
|
||||
View::showErrorPopup("hex.view.hexeditor.error.create"_lang);
|
||||
View::showErrorPopup("hex.builtin.view.hexeditor.error.create"_lang);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -190,12 +193,12 @@ namespace hex {
|
||||
this->getWindowOpenState() = true;
|
||||
});
|
||||
} else if (name == "Open File") {
|
||||
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
EventManager::post<RequestOpenFile>(path);
|
||||
this->getWindowOpenState() = true;
|
||||
});
|
||||
} else if (name == "Open Project") {
|
||||
hex::openFileBrowser("hex.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
||||
ProjectFile::load(path);
|
||||
this->getWindowOpenState() = true;
|
||||
});
|
||||
@@ -206,49 +209,57 @@ namespace hex {
|
||||
{
|
||||
auto alpha = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.highlight_alpha");
|
||||
|
||||
this->m_highlightAlpha = alpha;
|
||||
if (alpha.is_number())
|
||||
this->m_highlightAlpha = alpha;
|
||||
}
|
||||
|
||||
{
|
||||
auto columnCount = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.column_count");
|
||||
|
||||
this->m_memoryEditor.Cols = static_cast<int>(columnCount);
|
||||
if (columnCount.is_number())
|
||||
this->m_memoryEditor.Cols = static_cast<int>(columnCount);
|
||||
}
|
||||
|
||||
{
|
||||
auto hexii = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.hexii");
|
||||
|
||||
this->m_memoryEditor.OptShowHexII = static_cast<int>(hexii);
|
||||
if (hexii.is_number())
|
||||
this->m_memoryEditor.OptShowHexII = static_cast<int>(hexii);
|
||||
}
|
||||
|
||||
{
|
||||
auto ascii = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.ascii");
|
||||
|
||||
this->m_memoryEditor.OptShowAscii = static_cast<int>(ascii);
|
||||
if (ascii.is_number())
|
||||
this->m_memoryEditor.OptShowAscii = static_cast<int>(ascii);
|
||||
}
|
||||
|
||||
{
|
||||
auto advancedDecoding = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.advanced_decoding");
|
||||
|
||||
this->m_memoryEditor.OptShowAdvancedDecoding = static_cast<int>(advancedDecoding);
|
||||
if (advancedDecoding.is_number())
|
||||
this->m_memoryEditor.OptShowAdvancedDecoding = static_cast<int>(advancedDecoding);
|
||||
}
|
||||
|
||||
{
|
||||
auto greyOutZeros = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.grey_zeros");
|
||||
|
||||
this->m_memoryEditor.OptGreyOutZeroes = static_cast<int>(greyOutZeros);
|
||||
if (greyOutZeros.is_number())
|
||||
this->m_memoryEditor.OptGreyOutZeroes = static_cast<int>(greyOutZeros);
|
||||
}
|
||||
|
||||
{
|
||||
auto upperCaseHex = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.uppercase_hex");
|
||||
|
||||
this->m_memoryEditor.OptUpperCaseHex = static_cast<int>(upperCaseHex);
|
||||
if (upperCaseHex.is_number())
|
||||
this->m_memoryEditor.OptUpperCaseHex = static_cast<int>(upperCaseHex);
|
||||
}
|
||||
|
||||
{
|
||||
auto showExtraInfo = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.extra_info");
|
||||
|
||||
this->m_memoryEditor.OptShowExtraInfo = static_cast<int>(showExtraInfo);
|
||||
if (showExtraInfo.is_number())
|
||||
this->m_memoryEditor.OptShowExtraInfo = static_cast<int>(showExtraInfo);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -275,10 +286,10 @@ namespace hex {
|
||||
|
||||
size_t dataSize = (!ImHexApi::Provider::isValid() || !provider->isReadable()) ? 0x00 : provider->getSize();
|
||||
|
||||
this->m_memoryEditor.DrawWindow(View::toWindowName("hex.view.hexeditor.name").c_str(), &this->getWindowOpenState(), this, dataSize, dataSize == 0 ? 0x00 : provider->getBaseAddress());
|
||||
this->m_memoryEditor.DrawWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), &this->getWindowOpenState(), this, dataSize, dataSize == 0 ? 0x00 : provider->getBaseAddress() + provider->getCurrentPageAddress());
|
||||
|
||||
if (dataSize != 0x00) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.hexeditor.name").c_str())) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.hexeditor.name").c_str())) {
|
||||
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows))
|
||||
ImGui::OpenPopup("hex.menu.edit"_lang);
|
||||
@@ -289,7 +300,9 @@ namespace hex {
|
||||
}
|
||||
|
||||
if (provider->getPageCount() > 1) {
|
||||
ImGui::TextUnformatted(hex::format("hex.view.hexeditor.page"_lang, provider->getCurrentPage() + 1, provider->getPageCount()).c_str());
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextUnformatted(hex::format("hex.builtin.view.hexeditor.page"_lang, provider->getCurrentPage() + 1, provider->getPageCount()).c_str());
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -321,7 +334,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
static void saveAs() {
|
||||
hex::openFileBrowser("hex.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.save_as"_lang, DialogMode::Save, { }, [](auto path) {
|
||||
ImHexApi::Provider::get()->saveAs(path);
|
||||
});
|
||||
}
|
||||
@@ -329,9 +342,9 @@ namespace hex {
|
||||
void ViewHexEditor::drawAlwaysVisible() {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (ImGui::BeginPopupModal("hex.view.hexeditor.exit_application.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::BeginPopupModal("hex.builtin.view.hexeditor.exit_application.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.view.hexeditor.exit_application.desc"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.hexeditor.exit_application.desc"_lang);
|
||||
ImGui::NewLine();
|
||||
|
||||
confirmButtons("hex.common.yes"_lang, "hex.common.no"_lang, [] {
|
||||
@@ -347,22 +360,22 @@ namespace hex {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("hex.view.hexeditor.script.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::BeginPopupModal("hex.builtin.view.hexeditor.script.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SetCursorPosX(10);
|
||||
ImGui::TextWrapped("%s", static_cast<const char *>("hex.view.hexeditor.script.desc"_lang));
|
||||
ImGui::TextWrapped("%s", static_cast<const char *>("hex.builtin.view.hexeditor.script.desc"_lang));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::InputText("##nolabel", this->m_loaderScriptScriptPath.data(), this->m_loaderScriptScriptPath.length(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("hex.view.hexeditor.script.script"_lang)) {
|
||||
hex::openFileBrowser("hex.view.hexeditor.script.script.title"_lang, DialogMode::Open, { { "Python Script", "py" } }, [this](auto path) {
|
||||
if (ImGui::Button("hex.builtin.view.hexeditor.script.script"_lang)) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.script.script.title"_lang, DialogMode::Open, { { "Python Script", "py" } }, [this](auto path) {
|
||||
this->m_loaderScriptScriptPath = path;
|
||||
});
|
||||
}
|
||||
ImGui::InputText("##nolabel", this->m_loaderScriptFilePath.data(), this->m_loaderScriptFilePath.length(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("hex.view.hexeditor.script.file"_lang)) {
|
||||
hex::openFileBrowser("hex.view.hexeditor.script.file.title"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
if (ImGui::Button("hex.builtin.view.hexeditor.script.file"_lang)) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.script.file.title"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
this->m_loaderScriptFilePath = path;
|
||||
});
|
||||
}
|
||||
@@ -390,7 +403,7 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("hex.view.hexeditor.menu.edit.set_base"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::BeginPopupModal("hex.builtin.view.hexeditor.menu.edit.set_base"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::InputText("hex.common.address"_lang, this->m_baseAddressBuffer, 16, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::NewLine();
|
||||
|
||||
@@ -408,7 +421,7 @@ namespace hex {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("hex.view.hexeditor.menu.edit.resize"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::BeginPopupModal("hex.builtin.view.hexeditor.menu.edit.resize"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::InputScalar("hex.common.size"_lang, ImGuiDataType_U64, &this->m_resizeSize, nullptr, nullptr, "0x%016llx", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::NewLine();
|
||||
|
||||
@@ -432,14 +445,14 @@ namespace hex {
|
||||
bool providerValid = ImHexApi::Provider::isValid();
|
||||
|
||||
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_file"_lang, "CTRL + O")) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.open_file"_lang, "CTRL + O")) {
|
||||
|
||||
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
EventManager::post<RequestOpenFile>(path);
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("hex.view.hexeditor.menu.file.open_recent"_lang, !SharedData::recentFilePaths.empty())) {
|
||||
if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.open_recent"_lang, !SharedData::recentFilePaths.empty())) {
|
||||
for (auto &path : SharedData::recentFilePaths) {
|
||||
if (ImGui::MenuItem(std::filesystem::path(path).filename().string().c_str())) {
|
||||
EventManager::post<RequestOpenFile>(path);
|
||||
@@ -449,35 +462,46 @@ namespace hex {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.save"_lang, "CTRL + S", false, providerValid && provider->isWritable())) {
|
||||
if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.open_other"_lang)) {
|
||||
|
||||
for (const auto &unlocalizedProviderName : ContentRegistry::Provider::getEntries()) {
|
||||
if (ImGui::MenuItem(LangEntry(unlocalizedProviderName))) {
|
||||
EventManager::post<RequestCreateProvider>(unlocalizedProviderName, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.save"_lang, "CTRL + S", false, providerValid && provider->isWritable())) {
|
||||
save();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.save_as"_lang, "CTRL + SHIFT + S", false, providerValid && provider->isWritable())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.save_as"_lang, "CTRL + SHIFT + S", false, providerValid && provider->isWritable())) {
|
||||
saveAs();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.close"_lang, "", false, providerValid && provider->isAvailable())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.close"_lang, "", false, providerValid)) {
|
||||
EventManager::post<EventFileUnloaded>();
|
||||
ImHexApi::Provider::remove(ImHexApi::Provider::get());
|
||||
providerValid = false;
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.quit"_lang, "", false)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.quit"_lang, "", false)) {
|
||||
ImHexApi::Common::closeImHex();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.open_project"_lang, "")) {
|
||||
hex::openFileBrowser("hex.view.hexeditor.menu.file.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.open_project"_lang, "")) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.menu.file.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) {
|
||||
ProjectFile::load(path);
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.save_project"_lang, "", false, providerValid && provider->isWritable())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.save_project"_lang, "", false, providerValid && provider->isWritable())) {
|
||||
if (ProjectFile::getProjectFilePath() == "") {
|
||||
hex::openFileBrowser("hex.view.hexeditor.save_project"_lang, DialogMode::Save, { { "Project File", "hexproj" } }, [](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.save_project"_lang, DialogMode::Save, { { "Project File", "hexproj" } }, [](auto path) {
|
||||
if (path.ends_with(".hexproj")) {
|
||||
ProjectFile::store(path);
|
||||
}
|
||||
@@ -490,18 +514,18 @@ namespace hex {
|
||||
ProjectFile::store();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.load_encoding_file"_lang)) {
|
||||
hex::openFileBrowser("hex.view.hexeditor.load_enconding_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.load_encoding_file"_lang)) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.load_enconding_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
this->m_currEncodingFile = EncodingFile(EncodingFile::Type::Thingy, path);
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("hex.view.hexeditor.menu.file.import"_lang)) {
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.base64"_lang)) {
|
||||
if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.import"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.import.base64"_lang)) {
|
||||
|
||||
hex::openFileBrowser("hex.view.hexeditor.menu.file.import.base64"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.menu.file.import.base64"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
std::vector<u8> base64;
|
||||
this->loadFromFile(path, base64);
|
||||
|
||||
@@ -509,19 +533,19 @@ namespace hex {
|
||||
this->m_dataToSave = crypt::decode64(base64);
|
||||
|
||||
if (this->m_dataToSave.empty())
|
||||
View::showErrorPopup("hex.view.hexeditor.base64.import_error"_lang);
|
||||
View::showErrorPopup("hex.builtin.view.hexeditor.base64.import_error"_lang);
|
||||
else
|
||||
ImGui::OpenPopup("hex.view.hexeditor.save_data"_lang);
|
||||
ImGui::OpenPopup("hex.builtin.view.hexeditor.save_data"_lang);
|
||||
this->getWindowOpenState() = true;
|
||||
} else View::showErrorPopup("hex.view.hexeditor.file_open_error"_lang);
|
||||
} else View::showErrorPopup("hex.builtin.view.hexeditor.file_open_error"_lang);
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.ips"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.import.ips"_lang)) {
|
||||
|
||||
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
auto patchData = File(path, File::Mode::Read).readBytes();
|
||||
auto patch = hex::loadIPSPatch(patchData);
|
||||
|
||||
@@ -535,8 +559,8 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.ips32"_lang)) {
|
||||
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.import.ips32"_lang)) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) {
|
||||
auto patchData = File(path, File::Mode::Read).readBytes();
|
||||
auto patch = hex::loadIPS32Patch(patchData);
|
||||
|
||||
@@ -548,17 +572,17 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.import.script"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.import.script"_lang)) {
|
||||
this->m_loaderScriptFilePath.clear();
|
||||
this->m_loaderScriptScriptPath.clear();
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.view.hexeditor.script.title"_lang); });
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.builtin.view.hexeditor.script.title"_lang); });
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("hex.view.hexeditor.menu.file.export"_lang, providerValid && provider->isWritable())) {
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.export.ips"_lang)) {
|
||||
if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.file.export"_lang, providerValid && provider->isWritable())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.export.ips"_lang)) {
|
||||
Patches patches = provider->getPatches();
|
||||
if (!patches.contains(0x00454F45) && patches.contains(0x00454F46)) {
|
||||
u8 value = 0;
|
||||
@@ -567,11 +591,11 @@ namespace hex {
|
||||
}
|
||||
|
||||
this->m_dataToSave = generateIPSPatch(patches);
|
||||
hex::openFileBrowser("hex.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
this->saveToFile(path, this->m_dataToSave);
|
||||
});
|
||||
}
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.export.ips32"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.export.ips32"_lang)) {
|
||||
Patches patches = provider->getPatches();
|
||||
if (!patches.contains(0x00454F45) && patches.contains(0x45454F46)) {
|
||||
u8 value = 0;
|
||||
@@ -580,7 +604,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
this->m_dataToSave = generateIPS32Patch(patches);
|
||||
hex::openFileBrowser("hex.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.menu.file.export.title"_lang, DialogMode::Save, { }, [this](auto path) {
|
||||
this->saveToFile(path, this->m_dataToSave);
|
||||
});
|
||||
}
|
||||
@@ -592,14 +616,14 @@ namespace hex {
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.search"_lang, "CTRL + F")) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.search"_lang, "CTRL + F")) {
|
||||
this->getWindowOpenState() = true;
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.view.hexeditor.name").c_str(), "hex.view.hexeditor.menu.file.search"_lang);
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.search"_lang);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.file.goto"_lang, "CTRL + G")) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.file.goto"_lang, "CTRL + G")) {
|
||||
this->getWindowOpenState() = true;
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.view.hexeditor.name").c_str(), "hex.view.hexeditor.menu.file.goto"_lang);
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.goto"_lang);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
@@ -621,7 +645,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
ON_SCOPE_EXIT { ImGui::End(); };
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.hexeditor.name").c_str())) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.hexeditor.name").c_str())) {
|
||||
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) {
|
||||
if (ctrl && keys['Z']) {
|
||||
@@ -632,13 +656,13 @@ namespace hex {
|
||||
if (ImHexApi::Provider::isValid())
|
||||
ImHexApi::Provider::get()->redo();
|
||||
} else if (ctrl && keys['F']) {
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.view.hexeditor.name").c_str(), "hex.view.hexeditor.menu.file.search"_lang);
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.search"_lang);
|
||||
return true;
|
||||
} else if (ctrl && keys['G']) {
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.view.hexeditor.name").c_str(), "hex.view.hexeditor.menu.file.goto"_lang);
|
||||
ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.goto"_lang);
|
||||
return true;
|
||||
} else if (ctrl && keys['O']) {
|
||||
hex::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [](auto path) {
|
||||
EventManager::post<RequestOpenFile>(path);
|
||||
});
|
||||
return true;
|
||||
@@ -697,18 +721,28 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewHexEditor::openFile(const std::string &path) {
|
||||
ImHexApi::Provider::add<prv::FileProvider>(path);
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
hex::prv::Provider *provider = nullptr;
|
||||
EventManager::post<RequestCreateProvider>("hex.builtin.provider.file", &provider);
|
||||
|
||||
if (auto fileProvider = dynamic_cast<prv::FileProvider*>(provider)) {
|
||||
fileProvider->setPath(path);
|
||||
if (!fileProvider->open()) {
|
||||
View::showErrorPopup("hex.builtin.view.hexeditor.error.open"_lang);
|
||||
ImHexApi::Provider::remove(provider);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!provider->isWritable()) {
|
||||
this->m_memoryEditor.ReadOnly = true;
|
||||
View::showErrorPopup("hex.view.hexeditor.error.read_only"_lang);
|
||||
View::showErrorPopup("hex.builtin.view.hexeditor.error.read_only"_lang);
|
||||
} else {
|
||||
this->m_memoryEditor.ReadOnly = false;
|
||||
}
|
||||
|
||||
if (!provider->isAvailable()) {
|
||||
View::showErrorPopup("hex.view.hexeditor.error.open"_lang);
|
||||
View::showErrorPopup("hex.builtin.view.hexeditor.error.open"_lang);
|
||||
ImHexApi::Provider::remove(provider);
|
||||
|
||||
return;
|
||||
@@ -744,7 +778,7 @@ namespace hex {
|
||||
size_t copySize = (end - start) + 1;
|
||||
|
||||
std::vector<u8> buffer(copySize, 0x00);
|
||||
provider->readRelative(start, buffer.data(), buffer.size());
|
||||
provider->read(start + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), buffer.size());
|
||||
|
||||
std::string str;
|
||||
for (const auto &byte : buffer)
|
||||
@@ -793,7 +827,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
// Write bytes
|
||||
provider->writeRelative(start, buffer.data(), std::min(end - start + 1, buffer.size()));
|
||||
provider->read(start + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), std::min(end - start + 1, buffer.size()));
|
||||
}
|
||||
|
||||
void ViewHexEditor::copyString() const {
|
||||
@@ -806,7 +840,7 @@ namespace hex {
|
||||
|
||||
std::string buffer(copySize, 0x00);
|
||||
buffer.reserve(copySize + 1);
|
||||
provider->readRelative(start, buffer.data(), copySize);
|
||||
provider->read(start + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), copySize);
|
||||
|
||||
ImGui::SetClipboardText(buffer.c_str());
|
||||
}
|
||||
@@ -820,7 +854,7 @@ namespace hex {
|
||||
size_t copySize = (end - start) + 1;
|
||||
|
||||
std::vector<u8> buffer(copySize, 0x00);
|
||||
provider->readRelative(start, buffer.data(), buffer.size());
|
||||
provider->read(start + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), buffer.size());
|
||||
|
||||
std::string str;
|
||||
switch (language) {
|
||||
@@ -873,7 +907,7 @@ namespace hex {
|
||||
str += " };";
|
||||
break;
|
||||
case Language::Rust:
|
||||
str += "let data: [u8, " + std::to_string(buffer.size()) + "] = [ ";
|
||||
str += "let data: [u8; " + std::to_string(buffer.size()) + "] = [ ";
|
||||
|
||||
for (const auto &byte : buffer)
|
||||
str += hex::format("0x{0:02X}, ", byte);
|
||||
@@ -922,7 +956,7 @@ namespace hex {
|
||||
size_t copySize = (end - start) + 1;
|
||||
|
||||
std::vector<u8> buffer(copySize, 0x00);
|
||||
provider->readRelative(start, buffer.data(), buffer.size());
|
||||
provider->read(start + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), buffer.size());
|
||||
|
||||
std::string str = "Hex View 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n\n";
|
||||
|
||||
@@ -969,7 +1003,7 @@ namespace hex {
|
||||
size_t copySize = (end - start) + 1;
|
||||
|
||||
std::vector<u8> buffer(copySize, 0x00);
|
||||
provider->readRelative(start, buffer.data(), buffer.size());
|
||||
provider->read(start + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), buffer.size());
|
||||
|
||||
std::string str =
|
||||
R"(
|
||||
@@ -1025,7 +1059,7 @@ R"(
|
||||
ImGui::SetClipboardText(str.c_str());
|
||||
}
|
||||
|
||||
static std::vector<std::pair<u64, u64>> findString(prv::Provider* &provider, std::string string) {
|
||||
static std::vector<std::pair<u64, u64>> findString(hex::prv::Provider* &provider, std::string string) {
|
||||
std::vector<std::pair<u64, u64>> results;
|
||||
|
||||
u32 foundCharacters = 0;
|
||||
@@ -1034,7 +1068,7 @@ R"(
|
||||
size_t dataSize = provider->getSize();
|
||||
for (u64 offset = 0; offset < dataSize; offset += 1024) {
|
||||
size_t usedBufferSize = std::min(u64(buffer.size()), dataSize - offset);
|
||||
provider->readRelative(offset, buffer.data(), usedBufferSize);
|
||||
provider->read(offset + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), usedBufferSize);
|
||||
|
||||
for (u64 i = 0; i < usedBufferSize; i++) {
|
||||
if (buffer[i] == string[foundCharacters])
|
||||
@@ -1052,7 +1086,7 @@ R"(
|
||||
return results;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<u64, u64>> findHex(prv::Provider* &provider, std::string string) {
|
||||
static std::vector<std::pair<u64, u64>> findHex(hex::prv::Provider* &provider, std::string string) {
|
||||
std::vector<std::pair<u64, u64>> results;
|
||||
|
||||
if ((string.size() % 2) == 1)
|
||||
@@ -1072,7 +1106,7 @@ R"(
|
||||
size_t dataSize = provider->getSize();
|
||||
for (u64 offset = 0; offset < dataSize; offset += 1024) {
|
||||
size_t usedBufferSize = std::min(u64(buffer.size()), dataSize - offset);
|
||||
provider->readRelative(offset, buffer.data(), usedBufferSize);
|
||||
provider->read(offset + provider->getBaseAddress() + provider->getCurrentPageAddress(), buffer.data(), usedBufferSize);
|
||||
|
||||
for (u64 i = 0; i < usedBufferSize; i++) {
|
||||
if (buffer[i] == hex[foundCharacters])
|
||||
@@ -1139,10 +1173,10 @@ R"(
|
||||
|
||||
|
||||
ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetWindowContentRegionMin() - ImGui::GetStyle().WindowPadding);
|
||||
if (ImGui::BeginPopup("hex.view.hexeditor.menu.file.search"_lang)) {
|
||||
if (ImGui::BeginPopup("hex.builtin.view.hexeditor.menu.file.search"_lang)) {
|
||||
if (ImGui::BeginTabBar("searchTabs")) {
|
||||
std::vector<char> *currBuffer = nullptr;
|
||||
if (ImGui::BeginTabItem("hex.view.hexeditor.search.string"_lang)) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hexeditor.search.string"_lang)) {
|
||||
this->m_searchFunction = findString;
|
||||
this->m_lastSearchBuffer = &this->m_lastStringSearch;
|
||||
currBuffer = &this->m_searchStringBuffer;
|
||||
@@ -1152,7 +1186,7 @@ R"(
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.view.hexeditor.search.hex"_lang)) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hexeditor.search.hex"_lang)) {
|
||||
this->m_searchFunction = findHex;
|
||||
this->m_lastSearchBuffer = &this->m_lastHexSearch;
|
||||
currBuffer = &this->m_searchHexBuffer;
|
||||
@@ -1164,16 +1198,16 @@ R"(
|
||||
}
|
||||
|
||||
if (currBuffer != nullptr) {
|
||||
if (ImGui::Button("hex.view.hexeditor.search.find"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.hexeditor.search.find"_lang))
|
||||
Find(currBuffer->data());
|
||||
|
||||
if (!this->m_lastSearchBuffer->empty()) {
|
||||
if ((ImGui::Button("hex.view.hexeditor.search.find_next"_lang)))
|
||||
if ((ImGui::Button("hex.builtin.view.hexeditor.search.find_next"_lang)))
|
||||
FindNext();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if ((ImGui::Button("hex.view.hexeditor.search.find_prev"_lang)))
|
||||
if ((ImGui::Button("hex.builtin.view.hexeditor.search.find_prev"_lang)))
|
||||
FindPrevious();
|
||||
}
|
||||
}
|
||||
@@ -1191,10 +1225,10 @@ R"(
|
||||
auto dataSize = provider->getActualSize();
|
||||
|
||||
ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetWindowContentRegionMin() - ImGui::GetStyle().WindowPadding);
|
||||
if (ImGui::BeginPopup("hex.view.hexeditor.menu.file.goto"_lang)) {
|
||||
if (ImGui::BeginPopup("hex.builtin.view.hexeditor.menu.file.goto"_lang)) {
|
||||
if (ImGui::BeginTabBar("gotoTabs")) {
|
||||
u64 newOffset = 0;
|
||||
if (ImGui::BeginTabItem("hex.view.hexeditor.goto.offset.absolute"_lang)) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hexeditor.goto.offset.absolute"_lang)) {
|
||||
ImGui::InputScalar("hex", ImGuiDataType_U64, &this->m_gotoAddress, nullptr, nullptr, "%llx", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
if (this->m_gotoAddress < baseAddress || this->m_gotoAddress > baseAddress + dataSize)
|
||||
@@ -1204,7 +1238,7 @@ R"(
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.view.hexeditor.goto.offset.begin"_lang)) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hexeditor.goto.offset.begin"_lang)) {
|
||||
ImGui::InputScalar("hex", ImGuiDataType_U64, &this->m_gotoAddress, nullptr, nullptr, "%llx", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
if (this->m_gotoAddress < 0 || this->m_gotoAddress > dataSize)
|
||||
@@ -1214,7 +1248,7 @@ R"(
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.view.hexeditor.goto.offset.current"_lang)) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hexeditor.goto.offset.current"_lang)) {
|
||||
ImGui::InputScalar("dec", ImGuiDataType_S64, &this->m_gotoAddress, nullptr, nullptr, "%lld", ImGuiInputTextFlags_CharsDecimal);
|
||||
|
||||
s64 currSelectionOffset = std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd);
|
||||
@@ -1228,7 +1262,7 @@ R"(
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.view.hexeditor.goto.offset.end"_lang)) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hexeditor.goto.offset.end"_lang)) {
|
||||
ImGui::InputScalar("hex", ImGuiDataType_U64, &this->m_gotoAddress, nullptr, nullptr, "%llx", ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
if (this->m_gotoAddress < 0 || this->m_gotoAddress > dataSize)
|
||||
@@ -1239,8 +1273,8 @@ R"(
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::Button("hex.view.hexeditor.menu.file.goto"_lang)) {
|
||||
provider->setCurrentPage(std::floor(double(newOffset - baseAddress) / prv::Provider::PageSize));
|
||||
if (ImGui::Button("hex.builtin.view.hexeditor.menu.file.goto"_lang)) {
|
||||
provider->setCurrentPage(std::floor(double(newOffset - baseAddress) / hex::prv::Provider::PageSize));
|
||||
EventManager::post<RequestSelectionChange>(Region { newOffset, 1 });
|
||||
}
|
||||
|
||||
@@ -1254,58 +1288,58 @@ R"(
|
||||
void ViewHexEditor::drawEditPopup() {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
bool providerValid = ImHexApi::Provider::isValid();
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.undo"_lang, "CTRL + Z", false, providerValid))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.undo"_lang, "CTRL + Z", false, providerValid))
|
||||
provider->undo();
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.redo"_lang, "CTRL + Y", false, providerValid))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.redo"_lang, "CTRL + Y", false, providerValid))
|
||||
provider->redo();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
bool bytesSelected = this->m_memoryEditor.DataPreviewAddr != -1 && this->m_memoryEditor.DataPreviewAddrEnd != -1;
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.copy"_lang, "CTRL + C", false, bytesSelected))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.copy"_lang, "CTRL + C", false, bytesSelected))
|
||||
this->copyBytes();
|
||||
|
||||
if (ImGui::BeginMenu("hex.view.hexeditor.menu.edit.copy_as"_lang, bytesSelected)) {
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.hex"_lang, "CTRL + SHIFT + C"))
|
||||
if (ImGui::BeginMenu("hex.builtin.view.hexeditor.menu.edit.copy_as"_lang, bytesSelected)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.hex"_lang, "CTRL + SHIFT + C"))
|
||||
this->copyString();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.c"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.c"_lang))
|
||||
this->copyLanguageArray(Language::C);
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.cpp"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.cpp"_lang))
|
||||
this->copyLanguageArray(Language::Cpp);
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.csharp"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.csharp"_lang))
|
||||
this->copyLanguageArray(Language::CSharp);
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.rust"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.rust"_lang))
|
||||
this->copyLanguageArray(Language::Rust);
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.python"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.python"_lang))
|
||||
this->copyLanguageArray(Language::Python);
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.java"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.java"_lang))
|
||||
this->copyLanguageArray(Language::Java);
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.js"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.js"_lang))
|
||||
this->copyLanguageArray(Language::JavaScript);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.ascii"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.ascii"_lang))
|
||||
this->copyHexView();
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.copy.html"_lang))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.copy.html"_lang))
|
||||
this->copyHexViewHTML();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.paste"_lang, "CTRL + V", false, bytesSelected))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.paste"_lang, "CTRL + V", false, bytesSelected))
|
||||
this->pasteBytes();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.select_all"_lang, "CTRL + A", false, providerValid))
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.select_all"_lang, "CTRL + A", false, providerValid))
|
||||
EventManager::post<RequestSelectionChange>(Region { provider->getBaseAddress(), provider->getActualSize() });
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.bookmark"_lang, nullptr, false, this->m_memoryEditor.DataPreviewAddr != -1 && this->m_memoryEditor.DataPreviewAddrEnd != -1)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.bookmark"_lang, nullptr, false, this->m_memoryEditor.DataPreviewAddr != -1 && this->m_memoryEditor.DataPreviewAddrEnd != -1)) {
|
||||
auto base = ImHexApi::Provider::get()->getBaseAddress();
|
||||
|
||||
size_t start = base + std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd);
|
||||
@@ -1314,15 +1348,15 @@ R"(
|
||||
ImHexApi::Bookmarks::add(start, end - start + 1, { }, { });
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.set_base"_lang, nullptr, false, providerValid && provider->isReadable())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.set_base"_lang, nullptr, false, providerValid && provider->isReadable())) {
|
||||
std::memset(this->m_baseAddressBuffer, 0x00, sizeof(this->m_baseAddressBuffer));
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.view.hexeditor.menu.edit.set_base"_lang); });
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.builtin.view.hexeditor.menu.edit.set_base"_lang); });
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.resize"_lang, nullptr, false, providerValid && provider->isResizable())) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.hexeditor.menu.edit.resize"_lang, nullptr, false, providerValid && provider->isResizable())) {
|
||||
View::doLater([this]{
|
||||
this->m_resizeSize = ImHexApi::Provider::get()->getActualSize();
|
||||
ImGui::OpenPopup("hex.view.hexeditor.menu.edit.resize"_lang);
|
||||
ImGui::OpenPopup("hex.builtin.view.hexeditor.menu.edit.resize"_lang);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_information.hpp"
|
||||
#include "content/views/view_information.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
@@ -18,11 +18,11 @@
|
||||
#include <imgui_imhex_extensions.h>
|
||||
#include <implot.h>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using namespace hex::literals;
|
||||
|
||||
ViewInformation::ViewInformation() : View("hex.view.information.name") {
|
||||
ViewInformation::ViewInformation() : View("hex.builtin.view.information.name") {
|
||||
EventManager::subscribe<EventDataChanged>(this, [this]() {
|
||||
this->m_dataValid = false;
|
||||
this->m_highestBlockEntropy = 0;
|
||||
@@ -39,30 +39,30 @@ namespace hex {
|
||||
if (this->m_blockSize != 0)
|
||||
this->m_entropyHandlePosition = region.address / this->m_blockSize;
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventFileUnloaded>(this, [this]{
|
||||
this->m_dataValid = false;
|
||||
});
|
||||
}
|
||||
|
||||
ViewInformation::~ViewInformation() {
|
||||
EventManager::unsubscribe<EventDataChanged>(this);
|
||||
EventManager::unsubscribe<EventRegionSelected>(this);
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
}
|
||||
|
||||
static float calculateEntropy(std::array<ImU64, 256> &valueCounts, size_t numBytes) {
|
||||
static float calculateEntropy(std::array<ImU64, 256> &valueCounts, size_t blockSize) {
|
||||
float entropy = 0;
|
||||
|
||||
if (numBytes == 0)
|
||||
return 0.0F;
|
||||
for (auto count : valueCounts) {
|
||||
if (count == 0) continue;
|
||||
|
||||
std::array<float, 256> floatValueCounts{ 0 };
|
||||
std::copy(valueCounts.begin(), valueCounts.end(), floatValueCounts.begin());
|
||||
float probability = static_cast<float>(count) / blockSize;
|
||||
|
||||
for (u16 i = 0; i < 256; i++) {
|
||||
floatValueCounts[i] /= float(numBytes);
|
||||
|
||||
if (floatValueCounts[i] > 0)
|
||||
entropy -= (floatValueCounts[i] * std::log2(floatValueCounts[i]));
|
||||
entropy += probability * std::log2(probability);
|
||||
}
|
||||
|
||||
return entropy / 8;
|
||||
return (-entropy) / 8; // log2(256) = 8
|
||||
}
|
||||
|
||||
void ViewInformation::analyze() {
|
||||
@@ -82,13 +82,16 @@ namespace hex {
|
||||
|
||||
for (u64 i = 0; i < provider->getSize(); i += this->m_blockSize) {
|
||||
std::array<ImU64, 256> blockValueCounts = { 0 };
|
||||
provider->readRelative(i, buffer.data(), std::min(u64(this->m_blockSize), provider->getSize() - i));
|
||||
provider->read(i + provider->getBaseAddress(), buffer.data(), std::min(u64(this->m_blockSize), provider->getSize() - i));
|
||||
|
||||
for (size_t j = 0; j < this->m_blockSize; j++) {
|
||||
blockValueCounts[buffer[j]]++;
|
||||
this->m_valueCounts[buffer[j]]++;
|
||||
}
|
||||
|
||||
this->m_blockEntropy.push_back(calculateEntropy(blockValueCounts, this->m_blockSize));
|
||||
|
||||
this->m_bytesAnalyzed = i;
|
||||
}
|
||||
|
||||
this->m_averageEntropy = calculateEntropy(this->m_valueCounts, provider->getSize());
|
||||
@@ -96,6 +99,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
{
|
||||
magic::compile();
|
||||
|
||||
this->m_fileDescription = magic::getDescription(provider);
|
||||
this->m_mimeType = magic::getMIMEType(provider);
|
||||
this->m_dataValid = true;
|
||||
@@ -106,64 +111,67 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewInformation::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.information.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.information.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav)) {
|
||||
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
ImGui::TextUnformatted("hex.view.information.control"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.control"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Disabled([this] {
|
||||
if (ImGui::Button("hex.view.information.analyze"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.information.analyze"_lang))
|
||||
this->analyze();
|
||||
}, this->m_analyzing);
|
||||
|
||||
if (this->m_analyzing) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextSpinner("hex.view.information.analyzing"_lang);
|
||||
ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang);
|
||||
ImGui::ProgressBar(this->m_bytesAnalyzed / static_cast<double>(provider->getSize()));
|
||||
} else {
|
||||
ImGui::NewLine();
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.region"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto &[name, value] : provider->getDataInformation()) {
|
||||
ImGui::LabelText(name.c_str(), "%s", value.c_str());
|
||||
}
|
||||
|
||||
if (this->m_dataValid) {
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.view.information.region"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto &[name, value] : provider->getDataInformation()) {
|
||||
ImGui::LabelText(name.c_str(), "%s", value.c_str());
|
||||
}
|
||||
|
||||
ImGui::LabelText("hex.view.information.region"_lang, "0x%llx - 0x%llx", this->m_analyzedRegion.first, this->m_analyzedRegion.second);
|
||||
ImGui::LabelText("hex.builtin.view.information.region"_lang, "0x%llx - 0x%llx", this->m_analyzedRegion.first, this->m_analyzedRegion.second);
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (!this->m_fileDescription.empty() || !this->m_mimeType.empty()) {
|
||||
ImGui::TextUnformatted("hex.view.information.magic"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.magic"_lang);
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
if (!this->m_fileDescription.empty()) {
|
||||
ImGui::TextUnformatted("hex.view.information.description"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.description"_lang);
|
||||
ImGui::TextWrapped("%s", this->m_fileDescription.c_str());
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
if (!this->m_mimeType.empty()) {
|
||||
ImGui::TextUnformatted("hex.view.information.mime"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.mime"_lang);
|
||||
ImGui::TextWrapped("%s", this->m_mimeType.c_str());
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("hex.view.information.info_analysis"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.info_analysis"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg));
|
||||
|
||||
ImGui::TextUnformatted("hex.view.information.distribution"_lang);
|
||||
ImPlot::SetNextPlotLimits(0, 256, 0, float(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##distribution", "Address", "Count", ImVec2(-1,0), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock)) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang);
|
||||
ImPlot::SetNextPlotLimits(0, 256, 0.5, float(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##distribution", "Address", "Count", ImVec2(-1,0), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock | ImPlotAxisFlags_LogScale)) {
|
||||
static auto x = []{
|
||||
std::array<ImU64, 256> result{ 0 };
|
||||
std::iota(result.begin(), result.end(), 0);
|
||||
@@ -178,10 +186,10 @@ namespace hex {
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::TextUnformatted("hex.view.information.entropy"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
|
||||
|
||||
ImPlot::SetNextPlotLimits(0, this->m_blockEntropy.size(), -0.1, 1.1, ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##entropy", "Address", "Entropy", ImVec2(-1,0), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_Lock)) {
|
||||
if (ImPlot::BeginPlot("##entropy", "Address", "Entropy", ImVec2(-1,0), ImPlotFlags_CanvasOnly | ImPlotFlags_AntiAliased, ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_Lock)) {
|
||||
ImPlot::PlotLine("##entropy_line", this->m_blockEntropy.data(), this->m_blockEntropy.size());
|
||||
|
||||
if (ImPlot::DragLineX("Position", &this->m_entropyHandlePosition, false)) {
|
||||
@@ -197,13 +205,13 @@ namespace hex {
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::LabelText("hex.view.information.block_size"_lang, "%s", hex::format("hex.view.information.block_size.desc"_lang, this->m_blockEntropy.size(), this->m_blockSize).c_str());
|
||||
ImGui::LabelText("hex.view.information.file_entropy"_lang, "%.8f", this->m_averageEntropy);
|
||||
ImGui::LabelText("hex.view.information.highest_entropy"_lang, "%.8f", this->m_highestBlockEntropy);
|
||||
ImGui::LabelText("hex.builtin.view.information.block_size"_lang, "%s", hex::format("hex.builtin.view.information.block_size.desc"_lang, this->m_blockEntropy.size(), this->m_blockSize).c_str());
|
||||
ImGui::LabelText("hex.builtin.view.information.file_entropy"_lang, "%.8f", this->m_averageEntropy);
|
||||
ImGui::LabelText("hex.builtin.view.information.highest_entropy"_lang, "%.8f", this->m_highestBlockEntropy);
|
||||
|
||||
if (this->m_averageEntropy > 0.83 && this->m_highestBlockEntropy > 0.9) {
|
||||
ImGui::NewLine();
|
||||
ImGui::TextColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "%s", static_cast<const char*>("hex.view.information.encrypted"_lang));
|
||||
ImGui::TextColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "%s", static_cast<const char*>("hex.builtin.view.information.encrypted"_lang));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "views/view_patches.hpp"
|
||||
#include "content/views/view_patches.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include "helpers/project_file_handler.hpp"
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewPatches::ViewPatches() : View("hex.view.patches.name") {
|
||||
ViewPatches::ViewPatches() : View("hex.builtin.view.patches.name") {
|
||||
EventManager::subscribe<EventProjectFileStore>(this, []{
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid())
|
||||
@@ -30,7 +30,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewPatches::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.patches.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.patches.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
@@ -38,9 +38,9 @@ namespace hex {
|
||||
if (ImGui::BeginTable("##patchesTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
||||
ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.patches.offset"_lang);
|
||||
ImGui::TableSetupColumn("hex.view.patches.orig"_lang);
|
||||
ImGui::TableSetupColumn("hex.view.patches.patch"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.patches.offset"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.patches.orig"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.patches.patch"_lang);
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("PatchContextMenu")) {
|
||||
if (ImGui::MenuItem("hex.view.patches.remove"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.patches.remove"_lang)) {
|
||||
patches.erase(this->m_selectedPatch);
|
||||
ProjectFile::markDirty();
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "views/view_pattern_data.hpp"
|
||||
#include "content/views/view_pattern_data.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/pattern_language/pattern_data.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewPatternData::ViewPatternData() : View("hex.view.pattern_data.name") {
|
||||
ViewPatternData::ViewPatternData() : View("hex.builtin.view.pattern_data.name") {
|
||||
|
||||
EventManager::subscribe<EventPatternChanged>(this, [this]() {
|
||||
this->m_sortedPatternData.clear();
|
||||
@@ -19,12 +19,12 @@ namespace hex {
|
||||
static bool beginPatternDataTable(prv::Provider* &provider, const std::vector<pl::PatternData*> &patterns, std::vector<pl::PatternData*> &sortedPatterns) {
|
||||
if (ImGui::BeginTable("##patterndatatable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.pattern_data.name"_lang, 0, -1, ImGui::GetID("name"));
|
||||
ImGui::TableSetupColumn("hex.view.pattern_data.color"_lang, 0, -1, ImGui::GetID("color"));
|
||||
ImGui::TableSetupColumn("hex.view.pattern_data.offset"_lang, 0, -1, ImGui::GetID("offset"));
|
||||
ImGui::TableSetupColumn("hex.view.pattern_data.size"_lang, 0, -1, ImGui::GetID("size"));
|
||||
ImGui::TableSetupColumn("hex.view.pattern_data.type"_lang, 0, -1, ImGui::GetID("type"));
|
||||
ImGui::TableSetupColumn("hex.view.pattern_data.value"_lang, 0, -1, ImGui::GetID("value"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.var_name"_lang, 0, -1, ImGui::GetID("name"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.color"_lang, 0, -1, ImGui::GetID("color"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.offset"_lang, 0, -1, ImGui::GetID("offset"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.size"_lang, 0, -1, ImGui::GetID("size"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.type"_lang, 0, -1, ImGui::GetID("type"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.value"_lang, 0, -1, ImGui::GetID("value"));
|
||||
|
||||
auto sortSpecs = ImGui::TableGetSortSpecs();
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewPatternData::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.pattern_data.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.pattern_data.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "views/view_pattern_editor.hpp"
|
||||
#include "content/views/view_pattern_editor.hpp"
|
||||
|
||||
#include "helpers/project_file_handler.hpp"
|
||||
#include <hex/helpers/project_file_handler.hpp>
|
||||
#include <hex/pattern_language/preprocessor.hpp>
|
||||
#include <hex/pattern_language/pattern_data.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using namespace hex::literals;
|
||||
namespace fs = std::filesystem;
|
||||
@@ -24,7 +24,7 @@ namespace hex {
|
||||
static TextEditor::LanguageDefinition langDef;
|
||||
if (!initialized) {
|
||||
static const char* const keywords[] = {
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "this", "parent", "addressof", "sizeof", "$", "while", "fn", "return", "namespace"
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "this", "parent", "addressof", "sizeof", "$", "while", "for", "fn", "return", "namespace"
|
||||
};
|
||||
for (auto& k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
@@ -82,12 +82,14 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
ViewPatternEditor::ViewPatternEditor() : View("hex.view.pattern.name") {
|
||||
ViewPatternEditor::ViewPatternEditor() : View("hex.builtin.view.pattern_editor.name") {
|
||||
this->m_patternLanguageRuntime = new pl::PatternLanguage();
|
||||
|
||||
this->m_textEditor.SetLanguageDefinition(PatternLanguage());
|
||||
this->m_textEditor.SetShowWhitespaces(false);
|
||||
|
||||
this->m_envVarEntries = { { "", s128(0), EnvVarType::Integer } };
|
||||
|
||||
EventManager::subscribe<EventProjectFileStore>(this, [this]() {
|
||||
ProjectFile::setPattern(this->m_textEditor.GetText());
|
||||
});
|
||||
@@ -147,11 +149,16 @@ namespace hex {
|
||||
|
||||
if (!this->m_possiblePatternFiles.empty()) {
|
||||
this->m_selectedPatternFile = 0;
|
||||
EventManager::post<RequestOpenPopup>("hex.view.pattern.accept_pattern"_lang);
|
||||
EventManager::post<RequestOpenPopup>("hex.builtin.view.pattern_editor.accept_pattern"_lang);
|
||||
this->m_acceptPatternWindowOpen = true;
|
||||
}
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventFileUnloaded>(this, [this]{
|
||||
this->m_textEditor.SetText("");
|
||||
this->m_patternLanguageRuntime->abort();
|
||||
});
|
||||
|
||||
/* Settings */
|
||||
{
|
||||
|
||||
@@ -181,16 +188,22 @@ namespace hex {
|
||||
EventManager::unsubscribe<RequestSetPatternLanguageCode>(this);
|
||||
EventManager::unsubscribe<EventFileLoaded>(this);
|
||||
EventManager::unsubscribe<RequestChangeTheme>(this);
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawMenu() {
|
||||
if (ImGui::BeginMenu("hex.menu.file"_lang)) {
|
||||
if (ImGui::MenuItem("hex.view.pattern.menu.file.load_pattern"_lang)) {
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.load_pattern"_lang)) {
|
||||
|
||||
this->m_selectedPatternFile = 0;
|
||||
this->m_possiblePatternFiles.clear();
|
||||
|
||||
for (auto &imhexPath : hex::getPath(ImHexPath::Patterns)) {
|
||||
if (!fs::exists(imhexPath)) continue;
|
||||
|
||||
for (auto &entry: fs::recursive_directory_iterator(imhexPath)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".hexpat") {
|
||||
this->m_possiblePatternFiles.push_back(entry.path());
|
||||
@@ -198,21 +211,30 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.view.pattern.menu.file.load_pattern"_lang); });
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.builtin.view.pattern_editor.menu.file.load_pattern"_lang); });
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.save_pattern"_lang)) {
|
||||
hex::openFileBrowser("hex.builtin.view.pattern_editor.menu.file.save_pattern"_lang, DialogMode::Save, { { "Pattern", "hexpat" }}, [this](const std::string &path) {
|
||||
File file(path, File::Mode::Create);
|
||||
|
||||
file.write(this->m_textEditor.GetText());
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.pattern.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_None | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.pattern_editor.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_None | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (ImHexApi::Provider::isValid() && provider->isAvailable()) {
|
||||
auto textEditorSize = ImGui::GetContentRegionAvail();
|
||||
textEditorSize.y *= 4.0/5.0;
|
||||
textEditorSize.y -= ImGui::GetTextLineHeightWithSpacing();
|
||||
this->m_textEditor.Render("hex.view.pattern.name"_lang, textEditorSize, true);
|
||||
this->m_textEditor.Render("hex.builtin.view.pattern_editor.name"_lang, textEditorSize, true);
|
||||
|
||||
auto consoleSize = ImGui::GetContentRegionAvail();
|
||||
consoleSize.y -= ImGui::GetTextLineHeightWithSpacing();
|
||||
@@ -245,26 +267,104 @@ namespace hex {
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
ImGui::Disabled([this] {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(ImColor(0x20, 0x85, 0x20)));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
|
||||
|
||||
if (ImGui::ArrowButton("evaluate", ImGuiDir_Right))
|
||||
if (this->m_evaluatorRunning) {
|
||||
if (ImGui::IconButton(ICON_VS_DEBUG_STOP, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed)))
|
||||
this->m_patternLanguageRuntime->abort();
|
||||
} else {
|
||||
if (ImGui::IconButton(ICON_VS_DEBUG_START, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)))
|
||||
this->parsePattern(this->m_textEditor.GetText().data());
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}, this->m_evaluatorRunning);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (this->m_evaluatorRunning)
|
||||
ImGui::TextSpinner("hex.view.pattern.evaluating"_lang);
|
||||
else
|
||||
if (ImGui::Checkbox("hex.view.pattern.auto"_lang, &this->m_runAutomatically)) {
|
||||
ImGui::TextSpinner("hex.builtin.view.pattern_editor.evaluating"_lang);
|
||||
else {
|
||||
if (ImGui::Checkbox("hex.builtin.view.pattern_editor.auto"_lang, &this->m_runAutomatically)) {
|
||||
if (this->m_runAutomatically)
|
||||
this->m_hasUnevaluatedChanges = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextUnformatted(hex::format("{} / {}",
|
||||
this->m_patternLanguageRuntime->getCreatedPatternCount(),
|
||||
this->m_patternLanguageRuntime->getMaximumPatternCount()
|
||||
).c_str()
|
||||
);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::IconButton(ICON_VS_GLOBE, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
||||
ImGui::OpenPopup("env_vars");
|
||||
|
||||
if (ImGui::BeginPopup("env_vars")) {
|
||||
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.env_vars"_lang);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) this->m_envVarEntries.push_back({ "", s128(0), EnvVarType::Integer });
|
||||
ImGui::Separator();
|
||||
|
||||
int index = 0;
|
||||
for (auto &[name, value, type] : this->m_envVarEntries) {
|
||||
ImGui::PushID(index++);
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetTextLineHeightWithSpacing() * 2);
|
||||
constexpr const char* Types[] = { "I", "F", "S", "B" };
|
||||
if (ImGui::BeginCombo("", Types[static_cast<int>(type)])) {
|
||||
for (auto i = 0; i < IM_ARRAYSIZE(Types); i++) {
|
||||
if (ImGui::Selectable(Types[i]))
|
||||
type = static_cast<EnvVarType>(i);
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::InputText("###name", name.data(), name.capacity(), ImGuiInputTextFlags_CallbackResize, ImGui::UpdateStringSizeCallback, &name);
|
||||
ImGui::SameLine();
|
||||
|
||||
switch (type) {
|
||||
case EnvVarType::Integer: {
|
||||
s64 displayValue = hex::get_or<s128>(value, 0);
|
||||
ImGui::InputScalar("###value", ImGuiDataType_S64, &displayValue);
|
||||
value = s128(displayValue);
|
||||
break;
|
||||
}
|
||||
case EnvVarType::Float: {
|
||||
auto displayValue = hex::get_or<double>(value, 0.0);
|
||||
ImGui::InputDouble("###value", &displayValue);
|
||||
value = displayValue;
|
||||
break;
|
||||
}
|
||||
case EnvVarType::Bool: {
|
||||
auto displayValue = hex::get_or<bool>(value, false);
|
||||
ImGui::Checkbox("###value", &displayValue);
|
||||
value = displayValue;
|
||||
break;
|
||||
}
|
||||
case EnvVarType::String: {
|
||||
auto displayValue = hex::get_or<std::string>(value, "");
|
||||
ImGui::InputText("###value", displayValue.data(), displayValue.capacity(), ImGuiInputTextFlags_CallbackResize, ImGui::UpdateStringSizeCallback, &displayValue);
|
||||
value = displayValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_textEditor.IsTextChanged()) {
|
||||
ProjectFile::markDirty();
|
||||
|
||||
@@ -284,8 +384,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawAlwaysVisible() {
|
||||
if (ImGui::BeginPopupModal("hex.view.pattern.accept_pattern"_lang, &this->m_acceptPatternWindowOpen, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextWrapped("%s", static_cast<const char *>("hex.view.pattern.accept_pattern.desc"_lang));
|
||||
if (ImGui::BeginPopupModal("hex.builtin.view.pattern_editor.accept_pattern"_lang, &this->m_acceptPatternWindowOpen, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::TextWrapped("%s", static_cast<const char *>("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang));
|
||||
|
||||
std::vector<std::string> entries;
|
||||
entries.resize(this->m_possiblePatternFiles.size());
|
||||
@@ -307,7 +407,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Text("%s", static_cast<const char *>("hex.view.pattern.accept_pattern.question"_lang));
|
||||
ImGui::Text("%s", static_cast<const char *>("hex.builtin.view.pattern_editor.accept_pattern.question"_lang));
|
||||
|
||||
confirmButtons("hex.common.yes"_lang, "hex.common.no"_lang, [this]{
|
||||
this->loadPatternFile(this->m_possiblePatternFiles[this->m_selectedPatternFile].string());
|
||||
@@ -322,7 +422,8 @@ namespace hex {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupModal("hex.view.pattern.menu.file.load_pattern"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
bool opened = true;
|
||||
if (ImGui::BeginPopupModal("hex.builtin.view.pattern_editor.menu.file.load_pattern"_lang, &opened, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
|
||||
if (ImGui::BeginListBox("##patterns", ImVec2(-FLT_MIN, 0))) {
|
||||
|
||||
@@ -344,7 +445,7 @@ namespace hex {
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.common.browse"_lang)) {
|
||||
hex::openFileBrowser("hex.view.pattern.open_pattern"_lang, DialogMode::Open, { { "Pattern File", "hexpat" } }, [this](auto path) {
|
||||
hex::openFileBrowser("hex.builtin.view.pattern_editor.open_pattern"_lang, DialogMode::Open, { { "Pattern File", "hexpat" } }, [this](auto path) {
|
||||
this->loadPatternFile(path);
|
||||
ImGui::CloseCurrentPopup();
|
||||
});
|
||||
@@ -396,7 +497,11 @@ namespace hex {
|
||||
EventManager::post<EventPatternChanged>();
|
||||
|
||||
std::thread([this, buffer = std::string(buffer)] {
|
||||
auto result = this->m_patternLanguageRuntime->executeString(ImHexApi::Provider::get(), buffer);
|
||||
std::map<std::string, pl::Token::Literal> envVars;
|
||||
for (const auto &[name, value, type] : this->m_envVarEntries)
|
||||
envVars.insert({ name, value });
|
||||
|
||||
auto result = this->m_patternLanguageRuntime->executeString(ImHexApi::Provider::get(), buffer, envVars);
|
||||
|
||||
auto error = this->m_patternLanguageRuntime->getError();
|
||||
if (error.has_value()) {
|
||||
@@ -417,4 +522,4 @@ namespace hex {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "content/views/view_provider_settings.hpp"
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewProviderSettings::ViewProviderSettings() : hex::View("hex.builtin.view.provider_settings.name") {
|
||||
EventManager::subscribe<EventProviderCreated>(this, [](hex::prv::Provider *provider){
|
||||
if (provider->hasLoadInterface())
|
||||
EventManager::post<RequestOpenPopup>(View::toWindowName("hex.builtin.view.provider_settings.load_popup"));
|
||||
});
|
||||
}
|
||||
|
||||
ViewProviderSettings::~ViewProviderSettings() {
|
||||
EventManager::unsubscribe<EventProviderCreated>(this);
|
||||
}
|
||||
|
||||
void ViewProviderSettings::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.provider_settings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
if (provider != nullptr)
|
||||
provider->drawInterface();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ViewProviderSettings::drawAlwaysVisible() {
|
||||
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.provider_settings.load_popup").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
if (provider != nullptr) {
|
||||
provider->drawLoadInterface();
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("hex.common.open"_lang)) {
|
||||
if (provider->open())
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.common.cancel"_lang)) {
|
||||
ImHexApi::Provider::remove(provider);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewProviderSettings::hasViewMenuItemEntry() {
|
||||
return this->isAvailable();
|
||||
}
|
||||
|
||||
bool ViewProviderSettings::isAvailable() {
|
||||
auto provider = hex::ImHexApi::Provider::get();
|
||||
|
||||
return provider != nullptr && provider->hasInterface();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
#include "views/view_settings.hpp"
|
||||
#include "content/views/view_settings.hpp"
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewSettings::ViewSettings() : View("hex.view.settings.name") {
|
||||
ViewSettings::ViewSettings() : View("hex.builtin.view.settings.name") {
|
||||
EventManager::subscribe<RequestOpenWindow>(this, [this](const std::string &name) {
|
||||
if (name == "Settings") {
|
||||
View::doLater([]{ ImGui::OpenPopup(View::toWindowName("hex.view.settings.name").c_str()); });
|
||||
View::doLater([]{ ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
});
|
||||
@@ -21,9 +21,8 @@ namespace hex {
|
||||
|
||||
void ViewSettings::drawContent() {
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX));
|
||||
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.view.settings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::SetNextWindowSize(ImVec2(500, 300) * SharedData::globalScale, ImGuiCond_Always);
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.settings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoResize)) {
|
||||
if (ImGui::BeginTabBar("settings")) {
|
||||
for (auto &[category, entries] : ContentRegistry::Settings::getEntries()) {
|
||||
if (ImGui::BeginTabItem(LangEntry(category))) {
|
||||
@@ -49,8 +48,11 @@ namespace hex {
|
||||
|
||||
void ViewSettings::drawMenu() {
|
||||
if (ImGui::BeginMenu("hex.menu.help"_lang)) {
|
||||
if (ImGui::MenuItem("hex.view.settings.name"_lang)) {
|
||||
View::doLater([]{ ImGui::OpenPopup(View::toWindowName("hex.view.settings.name").c_str()); });
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.view.settings.name"_lang)) {
|
||||
View::doLater([]{ ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "views/view_store.hpp"
|
||||
#include "content/views/view_store.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
@@ -16,23 +16,23 @@
|
||||
#include <microtar.h>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
ViewStore::ViewStore() : View("hex.view.store.name") {
|
||||
ViewStore::ViewStore() : View("hex.builtin.view.store.name") {
|
||||
this->refresh();
|
||||
}
|
||||
|
||||
ViewStore::~ViewStore() { }
|
||||
|
||||
void ViewStore::drawStore() {
|
||||
ImGui::Header("hex.view.store.desc"_lang, true);
|
||||
ImGui::Header("hex.builtin.view.store.desc"_lang, true);
|
||||
|
||||
if (ImGui::Button("hex.view.store.reload"_lang)) {
|
||||
if (ImGui::Button("hex.builtin.view.store.reload"_lang)) {
|
||||
this->refresh();
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ namespace hex {
|
||||
if (ImGui::BeginTabItem(title)) {
|
||||
if (ImGui::BeginTable("##pattern_language", 3, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_RowBg)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.store.row.name"_lang, ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("hex.view.store.row.description"_lang, ImGuiTableColumnFlags_None);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.store.row.name"_lang, ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.store.row.description"_lang, ImGuiTableColumnFlags_None);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
@@ -77,12 +77,17 @@ namespace hex {
|
||||
auto extractBasePath = this->m_downloadPath.parent_path() / this->m_downloadPath.stem();
|
||||
while (mtar_read_header(&ctx, &header) != MTAR_ENULLRECORD) {
|
||||
auto filePath = extractBasePath / fs::path(header.name);
|
||||
if (filePath.filename() == "@PaxHeader") {
|
||||
mtar_next(&ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::create_directories(filePath.parent_path());
|
||||
File outputFile(filePath.string(), File::Mode::Create);
|
||||
|
||||
std::vector<u8> buffer(0x10000);
|
||||
for (u64 offset = 0; offset < header.size; offset += buffer.size()) {
|
||||
auto readSize = std::min(buffer.size(), header.size - offset);
|
||||
auto readSize = std::min<u64>(buffer.size(), header.size - offset);
|
||||
mtar_read_data(&ctx, buffer.data(), readSize);
|
||||
|
||||
buffer.resize(readSize);
|
||||
@@ -104,17 +109,17 @@ namespace hex {
|
||||
}
|
||||
|
||||
} else if (entry.hasUpdate) {
|
||||
if (ImGui::Button("hex.view.store.update"_lang)) {
|
||||
if (ImGui::Button("hex.builtin.view.store.update"_lang)) {
|
||||
this->download(pathType, entry.fileName, entry.link, true);
|
||||
entry.downloading = true;
|
||||
}
|
||||
} else if (!entry.installed) {
|
||||
if (ImGui::Button("hex.view.store.download"_lang)) {
|
||||
if (ImGui::Button("hex.builtin.view.store.download"_lang)) {
|
||||
this->download(pathType, entry.fileName, entry.link, false);
|
||||
entry.downloading = true;
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Button("hex.view.store.remove"_lang)) {
|
||||
if (ImGui::Button("hex.builtin.view.store.remove"_lang)) {
|
||||
this->remove(pathType, entry.fileName);
|
||||
entry.installed = false;
|
||||
}
|
||||
@@ -136,13 +141,13 @@ namespace hex {
|
||||
|
||||
};
|
||||
|
||||
drawTab("hex.view.store.tab.patterns"_lang, ImHexPath::Patterns, this->m_patterns, [](auto){});
|
||||
drawTab("hex.view.store.tab.libraries"_lang, ImHexPath::PatternsInclude, this->m_includes, [](auto){});
|
||||
drawTab("hex.view.store.tab.magics"_lang, ImHexPath::Magic, this->m_magics, [](auto){
|
||||
drawTab("hex.builtin.view.store.tab.patterns"_lang, ImHexPath::Patterns, this->m_patterns, [](auto){});
|
||||
drawTab("hex.builtin.view.store.tab.libraries"_lang, ImHexPath::PatternsInclude, this->m_includes, [](auto){});
|
||||
drawTab("hex.builtin.view.store.tab.magics"_lang, ImHexPath::Magic, this->m_magics, [](auto){
|
||||
magic::compile();
|
||||
});
|
||||
drawTab("hex.view.store.tab.constants"_lang, ImHexPath::Constants, this->m_constants, [](auto){});
|
||||
drawTab("hex.view.store.tab.yara"_lang, ImHexPath::Yara, this->m_yara, [](auto){});
|
||||
drawTab("hex.builtin.view.store.tab.constants"_lang, ImHexPath::Constants, this->m_constants, [](auto){});
|
||||
drawTab("hex.builtin.view.store.tab.yara"_lang, ImHexPath::Yara, this->m_yara, [](auto){});
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
@@ -214,10 +219,10 @@ namespace hex {
|
||||
|
||||
void ViewStore::drawContent() {
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(600, 400) * SharedData::globalScale, ImVec2(FLT_MAX, FLT_MAX));
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.view.store.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.store.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
if (this->m_apiRequest.valid()) {
|
||||
if (this->m_apiRequest.wait_for(0s) != std::future_status::ready)
|
||||
ImGui::TextSpinner("hex.view.store.loading"_lang);
|
||||
ImGui::TextSpinner("hex.builtin.view.store.loading"_lang);
|
||||
else
|
||||
this->parseResponse();
|
||||
}
|
||||
@@ -232,8 +237,8 @@ namespace hex {
|
||||
|
||||
void ViewStore::drawMenu() {
|
||||
if (ImGui::BeginMenu("hex.menu.help"_lang)) {
|
||||
if (ImGui::MenuItem("hex.view.store.name"_lang)) {
|
||||
View::doLater([]{ ImGui::OpenPopup(View::toWindowName("hex.view.store.name").c_str()); });
|
||||
if (ImGui::MenuItem("hex.builtin.view.store.name"_lang)) {
|
||||
View::doLater([]{ ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
|
||||
this->getWindowOpenState() = true;
|
||||
}
|
||||
|
||||
@@ -244,7 +249,7 @@ namespace hex {
|
||||
|
||||
void ViewStore::download(ImHexPath pathType, const std::string &fileName, const std::string &url, bool update) {
|
||||
if (!update) {
|
||||
this->m_downloadPath = hex::getPath(pathType).front() / fs::path(fileName);
|
||||
this->m_downloadPath = hex::getPath(pathType).back() / fs::path(fileName);
|
||||
this->m_download = this->m_net.downloadFile(url, this->m_downloadPath);
|
||||
} else {
|
||||
for (const auto &path : hex::getPath(pathType)) {
|
||||
@@ -258,8 +263,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewStore::remove(ImHexPath pathType, const std::string &fileName) {
|
||||
for (const auto &path : hex::getPath(pathType))
|
||||
for (const auto &path : hex::getPath(pathType)) {
|
||||
fs::remove(path / fs::path(fileName));
|
||||
fs::remove(path / fs::path(fileName).stem());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +1,35 @@
|
||||
#include "views/view_strings.hpp"
|
||||
#include "content/views/view_strings.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <regex>
|
||||
|
||||
#include <llvm/Demangle/Demangle.h>
|
||||
#include <imgui_imhex_extensions.h>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewStrings::ViewStrings() : View("hex.view.strings.name") {
|
||||
ViewStrings::ViewStrings() : View("hex.builtin.view.strings.name") {
|
||||
EventManager::subscribe<EventDataChanged>(this, [this]() {
|
||||
this->m_foundStrings.clear();
|
||||
});
|
||||
|
||||
this->m_filter.reserve(0xFFFF);
|
||||
std::memset(this->m_filter.data(), 0x00, this->m_filter.capacity());
|
||||
|
||||
EventManager::subscribe<EventFileUnloaded>(this, [this]{
|
||||
this->m_foundStrings.clear();
|
||||
});
|
||||
}
|
||||
|
||||
ViewStrings::~ViewStrings() {
|
||||
EventManager::unsubscribe<EventDataChanged>(this);
|
||||
EventManager::unsubscribe<EventFileUnloaded>(this);
|
||||
}
|
||||
|
||||
std::string readString(const FoundString &foundString) {
|
||||
@@ -38,14 +45,14 @@ namespace hex {
|
||||
this->m_selectedString = readString(foundString);
|
||||
}
|
||||
if (ImGui::BeginPopup("StringContextMenu")) {
|
||||
if (ImGui::MenuItem("hex.view.strings.copy"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.strings.copy"_lang)) {
|
||||
ImGui::SetClipboardText(this->m_selectedString.c_str());
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("hex.view.strings.demangle"_lang)) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.strings.demangle"_lang)) {
|
||||
this->m_demangledName = llvm::demangle(this->m_selectedString);
|
||||
if (!this->m_demangledName.empty())
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.view.strings.demangle.name"_lang); });
|
||||
View::doLater([]{ ImGui::OpenPopup("hex.builtin.view.strings.demangle.name"_lang); });
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -64,7 +71,7 @@ namespace hex {
|
||||
|
||||
for (u64 offset = 0; offset < provider->getSize(); offset += buffer.size()) {
|
||||
size_t readSize = std::min(u64(buffer.size()), provider->getSize() - offset);
|
||||
provider->readRelative(offset, buffer.data(), readSize);
|
||||
provider->read(offset + provider->getBaseAddress(), buffer.data(), readSize);
|
||||
|
||||
for (u32 i = 0; i < readSize; i++) {
|
||||
if (buffer[i] >= ' ' && buffer[i] <= '~' && offset < provider->getSize() - 1)
|
||||
@@ -93,32 +100,53 @@ namespace hex {
|
||||
void ViewStrings::drawContent() {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.strings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.strings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
ImGui::Disabled([this]{
|
||||
if (ImGui::InputInt("hex.view.strings.min_length"_lang, &this->m_minimumLength, 1, 0))
|
||||
if (ImGui::InputInt("hex.builtin.view.strings.min_length"_lang, &this->m_minimumLength, 1, 0))
|
||||
this->m_foundStrings.clear();
|
||||
|
||||
ImGui::InputText("hex.view.strings.filter"_lang, this->m_filter.data(), this->m_filter.capacity(), ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) {
|
||||
ImGui::Checkbox("Regex", &this->m_regex);
|
||||
|
||||
ImGui::InputText("hex.builtin.view.strings.filter"_lang, this->m_filter.data(), this->m_filter.capacity(), ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) {
|
||||
auto &view = *static_cast<ViewStrings*>(data->UserData);
|
||||
view.m_filter.resize(data->BufTextLen);
|
||||
|
||||
view.m_filterIndices.clear();
|
||||
std::regex pattern;
|
||||
if (view.m_regex) {
|
||||
try {
|
||||
pattern = std::regex(data->Buf);
|
||||
view.m_pattern_parsed = true;
|
||||
} catch (std::regex_error &e) {
|
||||
view.m_pattern_parsed = false;
|
||||
}
|
||||
}
|
||||
for (u64 i = 0; i < view.m_foundStrings.size(); i++) {
|
||||
if (readString(view.m_foundStrings[i]).find(data->Buf) != std::string::npos)
|
||||
if (view.m_regex) {
|
||||
if(view.m_pattern_parsed && std::regex_search(readString(view.m_foundStrings[i]), pattern))
|
||||
view.m_filterIndices.push_back(i);
|
||||
}
|
||||
else if (readString(view.m_foundStrings[i]).find(data->Buf) != std::string::npos) {
|
||||
view.m_filterIndices.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}, this);
|
||||
if (this->m_regex && !this->m_pattern_parsed) {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "hex.builtin.view.strings.regex_error"_lang);
|
||||
}
|
||||
|
||||
if (ImGui::Button("hex.view.strings.extract"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.strings.extract"_lang))
|
||||
this->searchStrings();
|
||||
}, this->m_searching);
|
||||
|
||||
if (this->m_searching) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextSpinner("hex.view.strings.searching"_lang);
|
||||
ImGui::TextSpinner("hex.builtin.view.strings.searching"_lang);
|
||||
}
|
||||
else if (this->m_foundStrings.size() > 0) {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextUnformatted(hex::format("hex.builtin.view.strings.results"_lang, this->m_filterIndices.size()).c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -129,9 +157,9 @@ namespace hex {
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
||||
ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.view.strings.offset"_lang, 0, -1, ImGui::GetID("offset"));
|
||||
ImGui::TableSetupColumn("hex.view.strings.size"_lang, 0, -1, ImGui::GetID("size"));
|
||||
ImGui::TableSetupColumn("hex.view.strings.string"_lang, 0, -1, ImGui::GetID("string"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.strings.offset"_lang, 0, -1, ImGui::GetID("offset"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.strings.size"_lang, 0, -1, ImGui::GetID("size"));
|
||||
ImGui::TableSetupColumn("hex.builtin.view.strings.string"_lang, 0, -1, ImGui::GetID("string"));
|
||||
|
||||
auto sortSpecs = ImGui::TableGetSortSpecs();
|
||||
|
||||
@@ -196,13 +224,13 @@ namespace hex {
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (ImGui::BeginPopup("hex.view.strings.demangle.title"_lang)) {
|
||||
if (ImGui::BeginPopup("hex.builtin.view.strings.demangle.title"_lang)) {
|
||||
if (ImGui::BeginChild("##scrolling", ImVec2(500, 150))) {
|
||||
ImGui::TextUnformatted("hex.view.strings.demangle.title"_lang);
|
||||
ImGui::TextUnformatted("hex.builtin.view.strings.demangle.title"_lang);
|
||||
ImGui::Separator();
|
||||
ImGui::TextWrapped("%s", this->m_demangledName.c_str());
|
||||
ImGui::NewLine();
|
||||
if (ImGui::Button("hex.view.strings.demangle.copy"_lang))
|
||||
if (ImGui::Button("hex.builtin.view.strings.demangle.copy"_lang))
|
||||
ImGui::SetClipboardText(this->m_demangledName.c_str());
|
||||
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
#include "views/view_tools.hpp"
|
||||
#include "content/views/view_tools.hpp"
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewTools::ViewTools() : View("hex.view.tools.name") { }
|
||||
ViewTools::ViewTools() : View("hex.builtin.view.tools.name") { }
|
||||
|
||||
ViewTools::~ViewTools() { }
|
||||
|
||||
void ViewTools::drawContent() {
|
||||
if (ImGui::Begin(View::toWindowName("hex.view.tools.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
if (ImGui::Begin(View::toWindowName("hex.builtin.view.tools.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
||||
for (const auto& [name, function] : ContentRegistry::Tools::getEntries()) {
|
||||
if (ImGui::CollapsingHeader(LangEntry(name))) {
|
||||
function();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user