impr: Make decompression support actually useful (#1481)
This commit is contained in:
parent
b22d90f9ca
commit
950eaea8af
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -390,6 +390,7 @@ jobs:
|
|||||||
|
|
||||||
# Ubuntu cmake build
|
# Ubuntu cmake build
|
||||||
- name: 🛠️ Build
|
- name: 🛠️ Build
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
git config --global --add safe.directory '*'
|
git config --global --add safe.directory '*'
|
||||||
|
@ -2,7 +2,7 @@ macro(add_imhex_plugin)
|
|||||||
# Parse arguments
|
# Parse arguments
|
||||||
set(options LIBRARY_PLUGIN)
|
set(options LIBRARY_PLUGIN)
|
||||||
set(oneValueArgs NAME)
|
set(oneValueArgs NAME)
|
||||||
set(multiValueArgs SOURCES INCLUDES LIBRARIES)
|
set(multiValueArgs SOURCES INCLUDES LIBRARIES FEATURES)
|
||||||
cmake_parse_arguments(IMHEX_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
cmake_parse_arguments(IMHEX_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
if (IMHEX_STATIC_LINK_PLUGINS)
|
if (IMHEX_STATIC_LINK_PLUGINS)
|
||||||
@ -60,6 +60,11 @@ macro(add_imhex_plugin)
|
|||||||
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||||
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
|
target_link_libraries(${IMHEX_PLUGIN_NAME} PRIVATE ${LIBROMFS_LIBRARY})
|
||||||
|
|
||||||
|
foreach(feature ${IMHEX_PLUGIN_FEATURES})
|
||||||
|
string(TOUPPER ${feature} feature)
|
||||||
|
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# Add the new plugin to the main dependency list so it gets built by default
|
# Add the new plugin to the main dependency list so it gets built by default
|
||||||
if (TARGET imhex_all)
|
if (TARGET imhex_all)
|
||||||
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
|
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
|
||||||
@ -71,3 +76,13 @@ macro(add_romfs_resource input output)
|
|||||||
|
|
||||||
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)
|
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro (enable_plugin_feature feature)
|
||||||
|
string(TOUPPER ${feature} feature)
|
||||||
|
if (NOT (feature IN_LIST IMHEX_PLUGIN_FEATURES))
|
||||||
|
message(FATAL_ERROR "Feature ${feature} is not enabled for plugin ${IMHEX_PLUGIN_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
remove_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=0)
|
||||||
|
add_definitions(-DIMHEX_PLUGIN_${IMHEX_PLUGIN_NAME}_FEATURE_${feature}=1)
|
||||||
|
endmacro()
|
2
dist/Arch/PKGBUILD
vendored
2
dist/Arch/PKGBUILD
vendored
@ -8,7 +8,7 @@ pkgdesc="A Hex Editor for Reverse Engineers, Programmers and people who value th
|
|||||||
arch=("x86_64")
|
arch=("x86_64")
|
||||||
url="https://github.com/WerWolv/ImHex"
|
url="https://github.com/WerWolv/ImHex"
|
||||||
license=('GPL2')
|
license=('GPL2')
|
||||||
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json libarchive)
|
depends=(glfw mbedtls freetype2 libglvnd dbus gtk3 curl fmt yara nlohmann-json zlib bzip2 xz zstd)
|
||||||
makedepends=(git)
|
makedepends=(git)
|
||||||
provides=(imhex)
|
provides=(imhex)
|
||||||
conflicts=(imhex)
|
conflicts=(imhex)
|
||||||
|
5
dist/Brewfile
vendored
5
dist/Brewfile
vendored
@ -10,4 +10,7 @@ brew "gcc@12"
|
|||||||
brew "llvm"
|
brew "llvm"
|
||||||
brew "glfw"
|
brew "glfw"
|
||||||
brew "ninja"
|
brew "ninja"
|
||||||
brew "libarchive"
|
brew "zlib"
|
||||||
|
brew "xz"
|
||||||
|
brew "bzip2"
|
||||||
|
brew "zstd"
|
2
dist/DEBIAN/control.in
vendored
2
dist/DEBIAN/control.in
vendored
@ -4,7 +4,7 @@ Section: editors
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
License: GNU GPL-2
|
License: GNU GPL-2
|
||||||
Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal, libarchive13
|
Depends: libglfw3 | libglfw3-wayland, libmagic1, libmbedtls14, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
|
||||||
Maintainer: WerWolv <hey@werwolv.net>
|
Maintainer: WerWolv <hey@werwolv.net>
|
||||||
Description: ImHex Hex Editor
|
Description: ImHex Hex Editor
|
||||||
A Hex Editor for Reverse Engineers, Programmers and
|
A Hex Editor for Reverse Engineers, Programmers and
|
||||||
|
5
dist/ImHex-9999.ebuild
vendored
5
dist/ImHex-9999.ebuild
vendored
@ -24,6 +24,9 @@ RDEPEND="${DEPEND}
|
|||||||
dev-cpp/nlohmann_json
|
dev-cpp/nlohmann_json
|
||||||
dbus
|
dbus
|
||||||
xdg-desktop-portal
|
xdg-desktop-portal
|
||||||
app-arch/libarchive
|
sys-libs/zlib
|
||||||
|
app-arch/bzip2
|
||||||
|
app-arch/lzma
|
||||||
|
app-arch/zstd
|
||||||
"
|
"
|
||||||
BDEPEND="${DEPEND}"
|
BDEPEND="${DEPEND}"
|
||||||
|
5
dist/get_deps_archlinux.sh
vendored
5
dist/get_deps_archlinux.sh
vendored
@ -15,4 +15,7 @@ pacman -S $@ --needed \
|
|||||||
yara \
|
yara \
|
||||||
nlohmann-json \
|
nlohmann-json \
|
||||||
ninja \
|
ninja \
|
||||||
libarchive
|
zlib \
|
||||||
|
bzip2 \
|
||||||
|
xz \
|
||||||
|
zstd
|
||||||
|
5
dist/get_deps_debian.sh
vendored
5
dist/get_deps_debian.sh
vendored
@ -23,4 +23,7 @@ apt install -y \
|
|||||||
libcurl4-gnutls-dev \
|
libcurl4-gnutls-dev \
|
||||||
libgtk-3-dev \
|
libgtk-3-dev \
|
||||||
ninja-build \
|
ninja-build \
|
||||||
libarchive-dev
|
zlib1g-dev \
|
||||||
|
libbz2-dev \
|
||||||
|
liblzma-dev \
|
||||||
|
libzstd-dev
|
||||||
|
5
dist/get_deps_fedora.sh
vendored
5
dist/get_deps_fedora.sh
vendored
@ -13,4 +13,7 @@ dnf install -y \
|
|||||||
lld \
|
lld \
|
||||||
mbedtls-devel \
|
mbedtls-devel \
|
||||||
gtk3-devel \
|
gtk3-devel \
|
||||||
libarchive-devel
|
libzstd-devel \
|
||||||
|
zlib-devel \
|
||||||
|
bzip2-devel \
|
||||||
|
xz-devel
|
5
dist/get_deps_msys2.sh
vendored
5
dist/get_deps_msys2.sh
vendored
@ -13,4 +13,7 @@ pacman -S --needed --noconfirm \
|
|||||||
mingw-w64-x86_64-dlfcn \
|
mingw-w64-x86_64-dlfcn \
|
||||||
mingw-w64-x86_64-ninja \
|
mingw-w64-x86_64-ninja \
|
||||||
mingw-w64-x86_64-capstone \
|
mingw-w64-x86_64-capstone \
|
||||||
mingw-w64-x86_64-libarchive
|
mingw-w64-x86_64-zlib \
|
||||||
|
mingw-w64-x86_64-bzip2 \
|
||||||
|
mingw-w64-x86_64-xz \
|
||||||
|
mingw-w64-x86_64-zstd
|
||||||
|
8
dist/macOS/arm64.Dockerfile
vendored
8
dist/macOS/arm64.Dockerfile
vendored
@ -52,7 +52,10 @@ vcpkg install --triplet=arm-osx-mytriplet curl
|
|||||||
vcpkg install --triplet=arm-osx-mytriplet mbedtls
|
vcpkg install --triplet=arm-osx-mytriplet mbedtls
|
||||||
vcpkg install --triplet=arm-osx-mytriplet freetype
|
vcpkg install --triplet=arm-osx-mytriplet freetype
|
||||||
vcpkg install --triplet=arm-osx-mytriplet josuttis-jthread
|
vcpkg install --triplet=arm-osx-mytriplet josuttis-jthread
|
||||||
vcpkg install --triplet=arm-osx-mytriplet libarchive
|
vcpkg install --triplet=arm-osx-mytriplet zlib
|
||||||
|
vcpkg install --triplet=arm-osx-mytriplet bzip2
|
||||||
|
vcpkg install --triplet=arm-osx-mytriplet liblzma
|
||||||
|
vcpkg install --triplet=arm-osx-mytriplet zstd
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
## Install glfw3 dep
|
## Install glfw3 dep
|
||||||
@ -103,6 +106,9 @@ if [ "$CUSTOM_GLFW" ]; then
|
|||||||
fi
|
fi
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
RUN mkdir -p /vcpkg/installed/arm-osx-mytriplet/lib/pkgconfig
|
||||||
|
RUN mkdir -p /osxcross/target/macports/pkgs/vcpkg/installed/arm-osx-mytriplet/lib/pkgconfig
|
||||||
|
|
||||||
## Build glfw
|
## Build glfw
|
||||||
RUN --mount=type=cache,target=/cache <<EOF
|
RUN --mount=type=cache,target=/cache <<EOF
|
||||||
set -xe
|
set -xe
|
||||||
|
5
dist/msys2/PKGBUILD
vendored
5
dist/msys2/PKGBUILD
vendored
@ -17,7 +17,10 @@ makedepends=("${MINGW_PACKAGE_PREFIX}-gcc"
|
|||||||
"${MINGW_PACKAGE_PREFIX}-mbedtls"
|
"${MINGW_PACKAGE_PREFIX}-mbedtls"
|
||||||
"${MINGW_PACKAGE_PREFIX}-polly"
|
"${MINGW_PACKAGE_PREFIX}-polly"
|
||||||
"${MINGW_PACKAGE_PREFIX}-freetype"
|
"${MINGW_PACKAGE_PREFIX}-freetype"
|
||||||
"${MINGW_PACKAGE_PREFIX}-libarchive")
|
"${MINGW_PACKAGE_PREFIX}-zlib"
|
||||||
|
"${MINGW_PACKAGE_PREFIX}-bzip2"
|
||||||
|
"${MINGW_PACKAGE_PREFIX}-xz"
|
||||||
|
"${MINGW_PACKAGE_PREFIX}-zstd")
|
||||||
|
|
||||||
source=()
|
source=()
|
||||||
sha256sums=()
|
sha256sums=()
|
||||||
|
5
dist/rpm/imhex.spec
vendored
5
dist/rpm/imhex.spec
vendored
@ -27,7 +27,10 @@ BuildRequires: mbedtls-devel
|
|||||||
BuildRequires: yara-devel
|
BuildRequires: yara-devel
|
||||||
BuildRequires: nativefiledialog-extended-devel
|
BuildRequires: nativefiledialog-extended-devel
|
||||||
BuildRequires: dotnet-sdk-7.0
|
BuildRequires: dotnet-sdk-7.0
|
||||||
BuildRequires: libarchive-devel
|
BuildRequires: libzstd-devel
|
||||||
|
BuildRequires: zlib-devel
|
||||||
|
BuildRequires: bzip2-devel
|
||||||
|
BuildRequires: xz-devel
|
||||||
%if 0%{?rhel}
|
%if 0%{?rhel}
|
||||||
BuildRequires: gcc-toolset-12
|
BuildRequires: gcc-toolset-12
|
||||||
%endif
|
%endif
|
||||||
|
5
dist/web/Dockerfile
vendored
5
dist/web/Dockerfile
vendored
@ -37,7 +37,10 @@ mkdir -p $VCPKG_DEFAULT_BINARY_CACHE
|
|||||||
/vcpkg/vcpkg install --triplet=wasm32-emscripten libmagic
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten libmagic
|
||||||
/vcpkg/vcpkg install --triplet=wasm32-emscripten freetype
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten freetype
|
||||||
/vcpkg/vcpkg install --triplet=wasm32-emscripten mbedtls
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten mbedtls
|
||||||
/vcpkg/vcpkg install --triplet=wasm32-emscripten libarchive
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten zlib
|
||||||
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten bzip2
|
||||||
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten liblzma
|
||||||
|
/vcpkg/vcpkg install --triplet=wasm32-emscripten zstd
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Build ImHex
|
# Build ImHex
|
||||||
|
@ -17,6 +17,11 @@ namespace hex {
|
|||||||
std::function<void(const std::vector<std::string>&)> callback;
|
std::function<void(const std::vector<std::string>&)> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Feature {
|
||||||
|
std::string name;
|
||||||
|
bool enabled;
|
||||||
|
};
|
||||||
|
|
||||||
struct PluginFunctions {
|
struct PluginFunctions {
|
||||||
using InitializePluginFunc = void (*)();
|
using InitializePluginFunc = void (*)();
|
||||||
using InitializeLibraryFunc = void (*)();
|
using InitializeLibraryFunc = void (*)();
|
||||||
@ -27,6 +32,7 @@ namespace hex {
|
|||||||
using SetImGuiContextFunc = void (*)(ImGuiContext *);
|
using SetImGuiContextFunc = void (*)(ImGuiContext *);
|
||||||
using IsBuiltinPluginFunc = bool (*)();
|
using IsBuiltinPluginFunc = bool (*)();
|
||||||
using GetSubCommandsFunc = void* (*)();
|
using GetSubCommandsFunc = void* (*)();
|
||||||
|
using GetFeaturesFunc = void* (*)();
|
||||||
|
|
||||||
InitializePluginFunc initializePluginFunction = nullptr;
|
InitializePluginFunc initializePluginFunction = nullptr;
|
||||||
InitializeLibraryFunc initializeLibraryFunction = nullptr;
|
InitializeLibraryFunc initializeLibraryFunction = nullptr;
|
||||||
@ -37,6 +43,7 @@ namespace hex {
|
|||||||
SetImGuiContextFunc setImGuiContextFunction = nullptr;
|
SetImGuiContextFunc setImGuiContextFunction = nullptr;
|
||||||
IsBuiltinPluginFunc isBuiltinPluginFunction = nullptr;
|
IsBuiltinPluginFunc isBuiltinPluginFunction = nullptr;
|
||||||
GetSubCommandsFunc getSubCommandsFunction = nullptr;
|
GetSubCommandsFunc getSubCommandsFunction = nullptr;
|
||||||
|
GetFeaturesFunc getFeaturesFunction = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Plugin {
|
class Plugin {
|
||||||
@ -65,6 +72,7 @@ namespace hex {
|
|||||||
[[nodiscard]] bool isLoaded() const;
|
[[nodiscard]] bool isLoaded() const;
|
||||||
|
|
||||||
[[nodiscard]] std::span<SubCommand> getSubCommands() const;
|
[[nodiscard]] std::span<SubCommand> getSubCommands() const;
|
||||||
|
[[nodiscard]] std::span<Feature> getFeatures() const;
|
||||||
|
|
||||||
[[nodiscard]] bool isLibraryPlugin() const;
|
[[nodiscard]] bool isLibraryPlugin() const;
|
||||||
|
|
||||||
|
@ -92,3 +92,12 @@
|
|||||||
return &g_subCommands; \
|
return &g_subCommands; \
|
||||||
} \
|
} \
|
||||||
std::vector<hex::SubCommand> g_subCommands
|
std::vector<hex::SubCommand> g_subCommands
|
||||||
|
|
||||||
|
#define IMHEX_FEATURE_ENABLED(feature) WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(WOLV_TOKEN_CONCAT(IMHEX_PLUGIN_, IMHEX_PLUGIN_NAME), _FEATURE_), feature)
|
||||||
|
#define IMHEX_PLUGIN_FEATURES() IMHEX_PLUGIN_FEATURES_IMPL()
|
||||||
|
#define IMHEX_PLUGIN_FEATURES_IMPL() \
|
||||||
|
extern std::vector<hex::Feature> g_features; \
|
||||||
|
extern "C" [[gnu::visibility("default")]] void* getFeatures() { \
|
||||||
|
return &g_features; \
|
||||||
|
} \
|
||||||
|
std::vector<hex::Feature> g_features
|
||||||
|
@ -44,6 +44,7 @@ namespace hex {
|
|||||||
m_functions.setImGuiContextFunction = getPluginFunction<PluginFunctions::SetImGuiContextFunc>("setImGuiContext");
|
m_functions.setImGuiContextFunction = getPluginFunction<PluginFunctions::SetImGuiContextFunc>("setImGuiContext");
|
||||||
m_functions.isBuiltinPluginFunction = getPluginFunction<PluginFunctions::IsBuiltinPluginFunc>("isBuiltinPlugin");
|
m_functions.isBuiltinPluginFunction = getPluginFunction<PluginFunctions::IsBuiltinPluginFunc>("isBuiltinPlugin");
|
||||||
m_functions.getSubCommandsFunction = getPluginFunction<PluginFunctions::GetSubCommandsFunc>("getSubCommands");
|
m_functions.getSubCommandsFunction = getPluginFunction<PluginFunctions::GetSubCommandsFunc>("getSubCommands");
|
||||||
|
m_functions.getFeaturesFunction = getPluginFunction<PluginFunctions::GetSubCommandsFunc>("getFeatures");
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin::Plugin(const hex::PluginFunctions &functions) {
|
Plugin::Plugin(const hex::PluginFunctions &functions) {
|
||||||
@ -188,6 +189,15 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::span<Feature> Plugin::getFeatures() const {
|
||||||
|
if (m_functions.getFeaturesFunction != nullptr) {
|
||||||
|
auto result = m_functions.getFeaturesFunction();
|
||||||
|
return *static_cast<std::vector<Feature>*>(result);
|
||||||
|
} else {
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Plugin::isLibraryPlugin() const {
|
bool Plugin::isLibraryPlugin() const {
|
||||||
return m_functions.initializeLibraryFunction != nullptr &&
|
return m_functions.initializeLibraryFunction != nullptr &&
|
||||||
m_functions.initializePluginFunction == nullptr;
|
m_functions.initializePluginFunction == nullptr;
|
||||||
|
@ -342,7 +342,7 @@ namespace hex::plugin::builtin {
|
|||||||
ImGuiExt::BeginSubWindow("hex.builtin.view.help.about.plugins"_lang);
|
ImGuiExt::BeginSubWindow("hex.builtin.view.help.about.plugins"_lang);
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
{
|
{
|
||||||
if (ImGui::BeginTable("plugins", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit)) {
|
if (ImGui::BeginTable("plugins", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
|
||||||
ImGui::TableSetupScrollFreeze(0, 1);
|
ImGui::TableSetupScrollFreeze(0, 1);
|
||||||
ImGui::TableSetupColumn("hex.builtin.view.help.about.plugins.plugin"_lang);
|
ImGui::TableSetupColumn("hex.builtin.view.help.about.plugins.plugin"_lang);
|
||||||
ImGui::TableSetupColumn("hex.builtin.view.help.about.plugins.author"_lang);
|
ImGui::TableSetupColumn("hex.builtin.view.help.about.plugins.author"_lang);
|
||||||
@ -355,18 +355,40 @@ namespace hex::plugin::builtin {
|
|||||||
if (plugin.isLibraryPlugin())
|
if (plugin.isLibraryPlugin())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
auto features = plugin.getFeatures();
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGuiExt::TextFormattedColored(
|
bool open = false;
|
||||||
plugin.isBuiltinPlugin() ? ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_Highlight) : ImGui::GetStyleColorVec4(ImGuiCol_Text),
|
|
||||||
"{}", plugin.getPluginName().c_str()
|
ImGui::PushStyleColor(ImGuiCol_Text, plugin.isBuiltinPlugin() ? ImGuiExt::GetCustomColorU32(ImGuiCustomCol_Highlight) : ImGui::GetColorU32(ImGuiCol_Text));
|
||||||
);
|
if (features.empty())
|
||||||
|
ImGui::BulletText("%s", plugin.getPluginName().c_str());
|
||||||
|
else
|
||||||
|
open = ImGui::TreeNode(plugin.getPluginName().c_str());
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(plugin.getPluginAuthor().c_str());
|
ImGui::TextUnformatted(plugin.getPluginAuthor().c_str());
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(plugin.getPluginDescription().c_str());
|
ImGui::TextUnformatted(plugin.getPluginDescription().c_str());
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE);
|
ImGui::TextUnformatted(plugin.isLoaded() ? ICON_VS_CHECK : ICON_VS_CLOSE);
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
for (const auto &feature : plugin.getFeatures()) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGuiExt::TextFormatted(" {}", feature.name.c_str());
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(feature.enabled ? ICON_VS_CHECK : ICON_VS_CLOSE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
|
@ -2,17 +2,17 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
|
|
||||||
include(ImHexPlugin)
|
include(ImHexPlugin)
|
||||||
|
|
||||||
# Homebrew only ships a libarchive keg, include directories have to be set manually
|
macro(addOptionalLibrary package library)
|
||||||
if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
|
find_package(${package})
|
||||||
execute_process(
|
if (${package}_FOUND)
|
||||||
COMMAND brew --prefix libarchive
|
set_property(TARGET ${package}::${library} PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
OUTPUT_VARIABLE LIBARCHIVE_PREFIX
|
string(TOUPPER ${package} PACKAGE)
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
set(LIBRARIES ${LIBRARIES} ${package}::${library})
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
message(STATUS "Enabling decompression support using ${package} (${${package}_VERSION})")
|
||||||
)
|
enable_plugin_feature(${PACKAGE})
|
||||||
set(LibArchive_INCLUDE_DIR "${LIBARCHIVE_PREFIX}/include")
|
endif()
|
||||||
endif()
|
|
||||||
find_package(LibArchive REQUIRED)
|
endmacro()
|
||||||
|
|
||||||
add_imhex_plugin(
|
add_imhex_plugin(
|
||||||
NAME
|
NAME
|
||||||
@ -25,5 +25,21 @@ add_imhex_plugin(
|
|||||||
include
|
include
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
ui
|
ui
|
||||||
LibArchive::LibArchive
|
FEATURES
|
||||||
|
ZLIB
|
||||||
|
BZIP2
|
||||||
|
LIBLZMA
|
||||||
|
ZSTD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
find_package(zstd)
|
||||||
|
if (TARGET zstd::libzstd_static)
|
||||||
|
addOptionalLibrary(zstd libzstd_static)
|
||||||
|
elseif(TARGET zstd::libzstd_shared)
|
||||||
|
addOptionalLibrary(zstd libzstd_shared)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
addOptionalLibrary(ZLIB ZLIB)
|
||||||
|
addOptionalLibrary(BZip2 BZip2)
|
||||||
|
addOptionalLibrary(LibLZMA LibLZMA)
|
||||||
|
target_link_libraries(decompress PRIVATE ${LIBRARIES})
|
||||||
|
@ -1,58 +1,232 @@
|
|||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
|
#include <hex/plugin.hpp>
|
||||||
|
|
||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
#include <pl/core/evaluator.hpp>
|
#include <pl/core/evaluator.hpp>
|
||||||
#include <pl/patterns/pattern.hpp>
|
#include <pl/patterns/pattern.hpp>
|
||||||
|
|
||||||
#include <archive.h>
|
|
||||||
#include <archive_entry.h>
|
|
||||||
|
|
||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
|
#if IMHEX_FEATURE_ENABLED(ZLIB)
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
#if IMHEX_FEATURE_ENABLED(BZIP2)
|
||||||
|
#include <bzlib.h>
|
||||||
|
#endif
|
||||||
|
#if IMHEX_FEATURE_ENABLED(LIBLZMA)
|
||||||
|
#include <lzma.h>
|
||||||
|
#endif
|
||||||
|
#if IMHEX_FEATURE_ENABLED(ZSTD)
|
||||||
|
#include <zstd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace hex::plugin::decompress {
|
namespace hex::plugin::decompress {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::vector<u8> getCompressedData(pl::core::Evaluator *evaluator, const pl::core::Token::Literal &literal) {
|
||||||
|
const auto inputPattern = literal.toPattern();
|
||||||
|
|
||||||
|
std::vector<u8> compressedData;
|
||||||
|
compressedData.resize(inputPattern->getSize());
|
||||||
|
evaluator->readData(inputPattern->getOffset(), compressedData.data(), compressedData.size(), inputPattern->getSection());
|
||||||
|
|
||||||
|
return compressedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void registerPatternLanguageFunctions() {
|
void registerPatternLanguageFunctions() {
|
||||||
using namespace pl::core;
|
using namespace pl::core;
|
||||||
using FunctionParameterCount = pl::api::FunctionParameterCount;
|
using FunctionParameterCount = pl::api::FunctionParameterCount;
|
||||||
|
|
||||||
const pl::api::Namespace nsHexDec = { "builtin", "hex", "dec" };
|
const pl::api::Namespace nsHexDec = { "builtin", "hex", "dec" };
|
||||||
|
|
||||||
/* decompress() */
|
/* zlib_decompress(compressed_pattern, section_id) */
|
||||||
ContentRegistry::PatternLanguage::addFunction(nsHexDec, "decompress", FunctionParameterCount::exactly(2), [](Evaluator *evaluator, auto params) -> std::optional<Token::Literal> {
|
ContentRegistry::PatternLanguage::addFunction(nsHexDec, "zlib_decompress", FunctionParameterCount::exactly(2), [](Evaluator *evaluator, auto params) -> std::optional<Token::Literal> {
|
||||||
const auto inputPattern = params[0].toPattern();
|
#if IMHEX_FEATURE_ENABLED(ZLIB)
|
||||||
auto §ion = evaluator->getSection(params[1].toUnsigned());
|
auto compressedData = getCompressedData(evaluator, params[0]);
|
||||||
|
auto §ion = evaluator->getSection(params[1].toUnsigned());
|
||||||
|
|
||||||
std::vector<u8> compressedData;
|
z_stream stream = { };
|
||||||
compressedData.resize(inputPattern->getSize());
|
if (inflateInit(&stream) != Z_OK) {
|
||||||
evaluator->readData(inputPattern->getOffset(), compressedData.data(), compressedData.size(), inputPattern->getSection());
|
return false;
|
||||||
|
|
||||||
auto inArchive = archive_read_new();
|
|
||||||
ON_SCOPE_EXIT {
|
|
||||||
archive_read_close(inArchive);
|
|
||||||
archive_read_free(inArchive);
|
|
||||||
};
|
|
||||||
|
|
||||||
archive_read_support_filter_all(inArchive);
|
|
||||||
archive_read_support_format_raw(inArchive);
|
|
||||||
|
|
||||||
archive_read_open_memory(inArchive, compressedData.data(), compressedData.size());
|
|
||||||
|
|
||||||
archive_entry *entry = nullptr;
|
|
||||||
while (archive_read_next_header(inArchive, &entry) == ARCHIVE_OK) {
|
|
||||||
const void *block = nullptr;
|
|
||||||
size_t size = 0x00;
|
|
||||||
i64 offset = 0x00;
|
|
||||||
|
|
||||||
while (archive_read_data_block(inArchive, &block, &size, &offset) == ARCHIVE_OK) {
|
|
||||||
section.resize(section.size() + size);
|
|
||||||
std::memcpy(section.data(), block, size);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
section.resize(100);
|
||||||
|
|
||||||
|
stream.avail_in = compressedData.size();
|
||||||
|
stream.avail_out = section.size();
|
||||||
|
stream.next_in = compressedData.data();
|
||||||
|
stream.next_out = section.data();
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
inflateEnd(&stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (stream.avail_in != 0) {
|
||||||
|
auto res = inflate(&stream, Z_NO_FLUSH);
|
||||||
|
if (res == Z_STREAM_END) {
|
||||||
|
section.resize(section.size() - stream.avail_out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res != Z_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stream.avail_out != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
section.resize(section.size() * 2);
|
||||||
|
stream.next_out = section.data();
|
||||||
|
stream.avail_out = section.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
hex::unused(evaluator, params);
|
||||||
|
err::E0012.throwError("hex::dec::zlib_decompress is not available. Please recompile with zlib support.");
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
/* bzip_decompress(compressed_pattern, section_id) */
|
||||||
|
ContentRegistry::PatternLanguage::addFunction(nsHexDec, "bzip_decompress", FunctionParameterCount::exactly(2), [](Evaluator *evaluator, auto params) -> std::optional<Token::Literal> {
|
||||||
|
#if IMHEX_FEATURE_ENABLED(BZIP2)
|
||||||
|
auto compressedData = getCompressedData(evaluator, params[0]);
|
||||||
|
auto §ion = evaluator->getSection(params[1].toUnsigned());
|
||||||
|
|
||||||
|
bz_stream stream = { };
|
||||||
|
if (BZ2_bzDecompressInit(&stream, 0, 1) != Z_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.resize(100);
|
||||||
|
|
||||||
|
stream.avail_in = compressedData.size();
|
||||||
|
stream.avail_out = section.size();
|
||||||
|
stream.next_in = reinterpret_cast<char*>(compressedData.data());
|
||||||
|
stream.next_out = reinterpret_cast<char*>(section.data());
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
BZ2_bzDecompressEnd(&stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (stream.avail_in != 0) {
|
||||||
|
auto res = BZ2_bzDecompress(&stream);
|
||||||
|
if (res == BZ_STREAM_END) {
|
||||||
|
section.resize(section.size() - stream.avail_out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res != BZ_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stream.avail_out != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
section.resize(section.size() * 2);
|
||||||
|
stream.next_out = reinterpret_cast<char*>(section.data());
|
||||||
|
stream.avail_out = section.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
hex::unused(evaluator, params);
|
||||||
|
err::E0012.throwError("hex::dec::bzlib_decompress is not available. Please recompile with bzip2 support.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/* lzma_decompress(compressed_pattern, section_id) */
|
||||||
|
ContentRegistry::PatternLanguage::addFunction(nsHexDec, "lzma_decompress", FunctionParameterCount::exactly(2), [](Evaluator *evaluator, auto params) -> std::optional<Token::Literal> {
|
||||||
|
#if IMHEX_FEATURE_ENABLED(LIBLZMA)
|
||||||
|
auto compressedData = getCompressedData(evaluator, params[0]);
|
||||||
|
auto §ion = evaluator->getSection(params[1].toUnsigned());
|
||||||
|
|
||||||
|
lzma_stream stream = LZMA_STREAM_INIT;
|
||||||
|
if (lzma_auto_decoder(&stream, 0x10000, LZMA_IGNORE_CHECK) != Z_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.resize(100);
|
||||||
|
|
||||||
|
stream.avail_in = compressedData.size();
|
||||||
|
stream.avail_out = section.size();
|
||||||
|
stream.next_in = compressedData.data();
|
||||||
|
stream.next_out = section.data();
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
lzma_end(&stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
while (stream.avail_in != 0) {
|
||||||
|
auto res = lzma_code(&stream, LZMA_RUN);
|
||||||
|
if (res == BZ_STREAM_END) {
|
||||||
|
section.resize(section.size() - stream.avail_out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res != LZMA_OK && res != LZMA_STREAM_END)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stream.avail_out != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
section.resize(section.size() * 2);
|
||||||
|
stream.next_out = compressedData.data();
|
||||||
|
stream.avail_out = compressedData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
hex::unused(evaluator, params);
|
||||||
|
err::E0012.throwError("hex::dec::lzma_decompress is not available. Please recompile with liblzma support.");
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
/* zstd_decompress(compressed_pattern, section_id) */
|
||||||
|
ContentRegistry::PatternLanguage::addFunction(nsHexDec, "zstd_decompress", FunctionParameterCount::exactly(2), [](Evaluator *evaluator, auto params) -> std::optional<Token::Literal> {
|
||||||
|
#if IMHEX_FEATURE_ENABLED(ZSTD)
|
||||||
|
auto compressedData = getCompressedData(evaluator, params[0]);
|
||||||
|
auto §ion = evaluator->getSection(params[1].toUnsigned());
|
||||||
|
|
||||||
|
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||||
|
if (dctx == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
ZSTD_freeDCtx(dctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
const u8* source = compressedData.data();
|
||||||
|
size_t sourceSize = compressedData.size();
|
||||||
|
|
||||||
|
do {
|
||||||
|
size_t blockSize = ZSTD_getFrameContentSize(source, sourceSize);
|
||||||
|
|
||||||
|
if (blockSize == ZSTD_CONTENTSIZE_ERROR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.resize(section.size() + blockSize);
|
||||||
|
|
||||||
|
size_t decodedSize = ZSTD_decompressDCtx(dctx, section.data() + section.size() - blockSize, blockSize, source, sourceSize);
|
||||||
|
|
||||||
|
if (ZSTD_isError(decodedSize)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
source = source + sourceSize;
|
||||||
|
sourceSize = 0;
|
||||||
|
|
||||||
|
} while (sourceSize > 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
hex::unused(evaluator, params);
|
||||||
|
err::E0012.throwError("hex::dec::zstd_decompress is not available. Please recompile with zstd support.");
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,3 +19,10 @@ IMHEX_PLUGIN_SETUP("Decompressing", "WerWolv", "Support for decompressing data")
|
|||||||
|
|
||||||
registerPatternLanguageFunctions();
|
registerPatternLanguageFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMHEX_PLUGIN_FEATURES() {
|
||||||
|
{ "bzip2 Support", IMHEX_FEATURE_ENABLED(BZIP2) },
|
||||||
|
{ "zlib Support", IMHEX_FEATURE_ENABLED(ZLIB) },
|
||||||
|
{ "LZMA Support", IMHEX_FEATURE_ENABLED(LIBLZMA) },
|
||||||
|
{ "zstd Support", IMHEX_FEATURE_ENABLED(ZSTD) },
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user