sys: Merge splash screen and ImHex into one application
This fixes so many issues the previous implementation had, especially on Unix
This commit is contained in:
parent
d7811e2c55
commit
1f2fe6b93d
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/curl" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/fmt" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/nativefiledialog" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/external/xdgpp" vcs="Git" />
|
||||
|
@ -40,10 +40,13 @@ add_executable(imhex ${application_type}
|
||||
source/main.cpp
|
||||
source/window.cpp
|
||||
|
||||
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_handler.cpp
|
||||
source/helpers/plugin_manager.cpp
|
||||
source/helpers/encoding_file.cpp
|
||||
|
||||
source/providers/file_provider.cpp
|
||||
@ -68,7 +71,6 @@ add_executable(imhex ${application_type}
|
||||
${imhex_icon}
|
||||
)
|
||||
|
||||
set_target_properties(imhex PROPERTIES OUTPUT_NAME "imhexg")
|
||||
set_target_properties(imhex PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
target_link_directories(imhex PRIVATE ${CAPSTONE_LIBRARY_DIRS} ${MAGIC_LIBRARY_DIRS})
|
||||
|
||||
@ -78,8 +80,4 @@ else ()
|
||||
target_link_libraries(imhex magic ${CMAKE_DL_LIBS} capstone LLVMDemangle libimhex ${Python_LIBRARIES} dl pthread libyara)
|
||||
endif ()
|
||||
|
||||
set_target_properties(imhex PROPERTIES VERSION ${IMHEX_VERSION})
|
||||
add_subdirectory(splash)
|
||||
set_target_properties(splash PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
createPackage()
|
||||
|
@ -252,9 +252,9 @@ macro(createPackage)
|
||||
# Enforce DragNDrop packaging.
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
|
||||
install(TARGETS splash imhex BUNDLE DESTINATION .)
|
||||
install(TARGETS imhex BUNDLE DESTINATION .)
|
||||
else()
|
||||
install(TARGETS splash imhex RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(TARGETS imhex RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -44,16 +44,16 @@ namespace hex {
|
||||
};
|
||||
};
|
||||
|
||||
class PluginHandler {
|
||||
class PluginManager {
|
||||
public:
|
||||
PluginHandler() = delete;
|
||||
PluginManager() = delete;
|
||||
|
||||
static void load(std::string_view pluginFolder);
|
||||
static bool load(std::string_view pluginFolder);
|
||||
static void unload();
|
||||
static void reload();
|
||||
|
||||
static const auto& getPlugins() {
|
||||
return PluginHandler::s_plugins;
|
||||
return PluginManager::s_plugins;
|
||||
}
|
||||
|
||||
private:
|
@ -8,11 +8,11 @@
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
namespace hex::pre {
|
||||
namespace hex::init {
|
||||
|
||||
class WindowSplash {
|
||||
public:
|
||||
WindowSplash();
|
||||
WindowSplash(int &argc, char **&argv);
|
||||
~WindowSplash();
|
||||
|
||||
bool loop();
|
||||
@ -24,7 +24,7 @@ namespace hex::pre {
|
||||
private:
|
||||
GLFWwindow *m_window;
|
||||
std::mutex m_progressMutex;
|
||||
float m_progress;
|
||||
float m_progress = 0;
|
||||
std::string m_currTaskName;
|
||||
|
||||
void initGLFW();
|
22
include/init/tasks.hpp
Normal file
22
include/init/tasks.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::init {
|
||||
|
||||
struct Task {
|
||||
std::string name;
|
||||
std::function<bool()> function;
|
||||
};
|
||||
|
||||
struct Argument {
|
||||
std::string name, value;
|
||||
};
|
||||
|
||||
std::vector<Task> getInitTasks();
|
||||
std::vector<Task> getExitTasks();
|
||||
|
||||
std::vector<Argument>& getInitArguments();
|
||||
}
|
@ -21,7 +21,7 @@ namespace hex {
|
||||
|
||||
class ViewHexEditor : public View {
|
||||
public:
|
||||
ViewHexEditor(std::vector<lang::PatternData*> &patternData);
|
||||
ViewHexEditor();
|
||||
~ViewHexEditor() override;
|
||||
|
||||
void drawContent() override;
|
||||
@ -32,8 +32,6 @@ namespace hex {
|
||||
private:
|
||||
MemoryEditor m_memoryEditor;
|
||||
|
||||
std::vector<lang::PatternData*> &m_patternData;
|
||||
|
||||
std::map<u64, u32> m_highlightedBytes;
|
||||
|
||||
std::vector<char> m_searchStringBuffer;
|
||||
|
@ -18,7 +18,7 @@ namespace hex {
|
||||
|
||||
class ViewPattern : public View {
|
||||
public:
|
||||
explicit ViewPattern(std::vector<lang::PatternData*> &patternData);
|
||||
ViewPattern();
|
||||
~ViewPattern() override;
|
||||
|
||||
void drawMenu() override;
|
||||
@ -27,7 +27,6 @@ namespace hex {
|
||||
|
||||
private:
|
||||
lang::PatternLanguage *m_patternLanguageRuntime;
|
||||
std::vector<lang::PatternData*> &m_patternData;
|
||||
std::vector<std::string> m_possiblePatternFiles;
|
||||
int m_selectedPatternFile = 0;
|
||||
bool m_runAutomatically = false;
|
||||
|
@ -16,15 +16,13 @@ namespace hex {
|
||||
|
||||
class ViewPatternData : public View {
|
||||
public:
|
||||
ViewPatternData(std::vector<lang::PatternData*> &patternData);
|
||||
ViewPatternData();
|
||||
~ViewPatternData() override;
|
||||
|
||||
void drawContent() override;
|
||||
void drawMenu() override;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<lang::PatternData*> &m_patternData;
|
||||
std::vector<lang::PatternData*> m_sortedPatternData;
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace hex {
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window(int &argc, char **&argv);
|
||||
Window();
|
||||
~Window();
|
||||
|
||||
void loop();
|
||||
@ -26,9 +26,6 @@ namespace hex {
|
||||
friend void ImHexSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf);
|
||||
|
||||
bool setFont(const std::filesystem::path &font_path);
|
||||
|
||||
void initPlugins();
|
||||
void deinitPlugins();
|
||||
private:
|
||||
void frameBegin();
|
||||
void frameEnd();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include <hex/helpers/lang.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
using namespace hex::lang_literals;
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
|
40
plugins/libimhex/include/hex/helpers/logger.hpp
Normal file
40
plugins/libimhex/include/hex/helpers/logger.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/color.h>
|
||||
|
||||
namespace hex::log {
|
||||
|
||||
void debug(std::string_view fmt, auto ... args) {
|
||||
#if defined(DEBUG)
|
||||
fmt::print(fg(fmt::color::green_yellow) | fmt::emphasis::bold, "[DEBUG] ");
|
||||
fmt::print(fmt, args...);
|
||||
fmt::print("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void info(std::string_view fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::cadet_blue) | fmt::emphasis::bold, "[INFO] ");
|
||||
fmt::print(fmt, args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void warn(std::string_view fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::light_golden_rod_yellow) | fmt::emphasis::bold, "[WARN] ");
|
||||
fmt::print(fmt, args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void error(std::string_view fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::red) | fmt::emphasis::bold, "[ERROR] ");
|
||||
fmt::print(fmt, args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
void fatal(std::string_view fmt, auto ... args) {
|
||||
fmt::print(fg(fmt::color::purple) | fmt::emphasis::bold, "[FATAL] ");
|
||||
fmt::print(fmt, args...);
|
||||
fmt::print("\n");
|
||||
}
|
||||
|
||||
}
|
@ -25,6 +25,8 @@ namespace hex {
|
||||
|
||||
namespace prv { class Provider; }
|
||||
namespace dp { class Node; }
|
||||
namespace lang { class PatternData; }
|
||||
|
||||
class View;
|
||||
|
||||
class SharedData {
|
||||
@ -58,6 +60,7 @@ namespace hex {
|
||||
static u32 patternPaletteOffset;
|
||||
static std::string errorPopupMessage;
|
||||
static std::list<ImHexApi::Bookmarks::Entry> bookmarkEntries;
|
||||
static std::vector<lang::PatternData*> patternData;
|
||||
|
||||
static std::map<std::string, std::string> languageNames;
|
||||
static std::map<std::string, std::vector<LanguageDefinition>> languageDefinitions;
|
||||
|
@ -14,6 +14,7 @@ namespace hex {
|
||||
u32 SharedData::patternPaletteOffset;
|
||||
std::string SharedData::errorPopupMessage;
|
||||
std::list<ImHexApi::Bookmarks::Entry> SharedData::bookmarkEntries;
|
||||
std::vector<lang::PatternData*> SharedData::patternData;
|
||||
|
||||
std::map<std::string, std::string> SharedData::languageNames;
|
||||
std::map<std::string, std::vector<LanguageDefinition>> SharedData::languageDefinitions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "helpers/plugin_handler.hpp"
|
||||
#include "helpers/plugin_manager.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@ -71,26 +71,31 @@ namespace hex {
|
||||
return "";
|
||||
}
|
||||
|
||||
void PluginHandler::load(std::string_view pluginFolder) {
|
||||
bool PluginManager::load(std::string_view pluginFolder) {
|
||||
if (!std::filesystem::exists(pluginFolder))
|
||||
throw std::runtime_error("Failed to find plugin folder");
|
||||
return false;
|
||||
|
||||
PluginHandler::s_pluginFolder = pluginFolder;
|
||||
PluginManager::s_pluginFolder = pluginFolder;
|
||||
|
||||
for (auto& pluginPath : std::filesystem::directory_iterator(pluginFolder)) {
|
||||
if (pluginPath.is_regular_file() && pluginPath.path().extension() == ".hexplug")
|
||||
PluginHandler::s_plugins.emplace_back(pluginPath.path().string());
|
||||
}
|
||||
PluginManager::s_plugins.emplace_back(pluginPath.path().string());
|
||||
}
|
||||
|
||||
void PluginHandler::unload() {
|
||||
PluginHandler::s_plugins.clear();
|
||||
PluginHandler::s_pluginFolder.clear();
|
||||
if (PluginManager::s_plugins.empty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PluginHandler::reload() {
|
||||
PluginHandler::unload();
|
||||
PluginHandler::load(PluginHandler::s_pluginFolder);
|
||||
void PluginManager::unload() {
|
||||
PluginManager::s_plugins.clear();
|
||||
PluginManager::s_pluginFolder.clear();
|
||||
}
|
||||
|
||||
void PluginManager::reload() {
|
||||
PluginManager::unload();
|
||||
PluginManager::load(PluginManager::s_pluginFolder);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#include "splash_window.hpp"
|
||||
#include "init/splash_window.hpp"
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/shared_data.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
@ -17,28 +18,12 @@
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
namespace hex::pre {
|
||||
namespace hex::init {
|
||||
|
||||
static void centerWindow(GLFWwindow *window) {
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
if (!monitor)
|
||||
return;
|
||||
WindowSplash::WindowSplash(int &argc, char **&argv) {
|
||||
SharedData::mainArgc = argc;
|
||||
SharedData::mainArgv = argv;
|
||||
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
int monitorX, monitorY;
|
||||
glfwGetMonitorPos(monitor, &monitorX, &monitorY);
|
||||
|
||||
int windowWidth, windowHeight;
|
||||
glfwGetWindowSize(window, &windowWidth, &windowHeight);
|
||||
|
||||
glfwSetWindowPos(window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2);
|
||||
}
|
||||
|
||||
|
||||
WindowSplash::WindowSplash() {
|
||||
this->initGLFW();
|
||||
this->initImGui();
|
||||
}
|
||||
@ -84,13 +69,14 @@ namespace hex::pre {
|
||||
break;
|
||||
}
|
||||
|
||||
if (splashTexture == nullptr)
|
||||
if (splashTexture == nullptr) {
|
||||
log::fatal("Could not load splash screen image!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ON_SCOPE_EXIT { ImGui::UnloadImage(splashTexture); };
|
||||
|
||||
|
||||
auto done = processTasksAsync();
|
||||
auto tasksSucceeded = processTasksAsync();
|
||||
|
||||
while (!glfwWindowShouldClose(this->m_window)) {
|
||||
glfwPollEvents();
|
||||
@ -120,22 +106,42 @@ namespace hex::pre {
|
||||
|
||||
glfwSwapBuffers(this->m_window);
|
||||
|
||||
if (done.wait_for(0s) == std::future_status::ready) {
|
||||
return done.get();
|
||||
if (tasksSucceeded.wait_for(0s) == std::future_status::ready) {
|
||||
return tasksSucceeded.get();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void centerWindow(GLFWwindow *window) {
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
if (!monitor)
|
||||
return;
|
||||
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
int monitorX, monitorY;
|
||||
glfwGetMonitorPos(monitor, &monitorX, &monitorY);
|
||||
|
||||
int windowWidth, windowHeight;
|
||||
glfwGetWindowSize(window, &windowWidth, &windowHeight);
|
||||
|
||||
glfwSetWindowPos(window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2);
|
||||
}
|
||||
|
||||
void WindowSplash::initGLFW() {
|
||||
glfwSetErrorCallback([](int error, const char *description) {
|
||||
printf("GLFW Error: %d - %s\n", error, description);
|
||||
log::fatal("GLFW Error: {0} - {0}", error, description);
|
||||
exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
if (!glfwInit())
|
||||
if (!glfwInit()) {
|
||||
log::fatal("Failed to initialize GLFW!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
@ -145,17 +151,21 @@ namespace hex::pre {
|
||||
glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
|
||||
|
||||
this->m_window = glfwCreateWindow(640, 400, "ImHex", nullptr, nullptr);
|
||||
if (this->m_window == nullptr)
|
||||
if (this->m_window == nullptr) {
|
||||
log::fatal("Failed to create GLFW window!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
centerWindow(this->m_window);
|
||||
|
||||
glfwMakeContextCurrent(this->m_window);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
if (gladLoadGL() == 0)
|
||||
if (gladLoadGL() == 0) {
|
||||
log::fatal("Failed to load OpenGL Context!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowSplash::initImGui() {
|
||||
IMGUI_CHECKVERSION();
|
150
source/init/tasks.cpp
Normal file
150
source/init/tasks.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "init/tasks.hpp"
|
||||
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include "views/view_hexeditor.hpp"
|
||||
#include "views/view_pattern.hpp"
|
||||
#include "views/view_pattern_data.hpp"
|
||||
#include "views/view_hashes.hpp"
|
||||
#include "views/view_information.hpp"
|
||||
#include "views/view_help.hpp"
|
||||
#include "views/view_tools.hpp"
|
||||
#include "views/view_strings.hpp"
|
||||
#include "views/view_data_inspector.hpp"
|
||||
#include "views/view_disassembler.hpp"
|
||||
#include "views/view_bookmarks.hpp"
|
||||
#include "views/view_patches.hpp"
|
||||
#include "views/view_command_palette.hpp"
|
||||
#include "views/view_settings.hpp"
|
||||
#include "views/view_data_processor.hpp"
|
||||
#include "views/view_yara.hpp"
|
||||
|
||||
#include "helpers/plugin_manager.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace hex::init {
|
||||
|
||||
static bool checkForUpdates() {
|
||||
hex::Net net;
|
||||
|
||||
auto releases = net.getJson("https://api.github.com/repos/WerWolv/ImHex/releases/latest");
|
||||
if (releases.code != 200)
|
||||
return false;
|
||||
|
||||
if (!releases.response.contains("tag_name") || !releases.response["tag_name"].is_string())
|
||||
return false;
|
||||
|
||||
auto currVersion = "v" + std::string(IMHEX_VERSION).substr(0, 5);
|
||||
auto latestVersion = releases.response["tag_name"].get<std::string_view>();
|
||||
|
||||
if (latestVersion != currVersion)
|
||||
getInitArguments().push_back({ "update-available", latestVersion.data() });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool createDirectories() {
|
||||
|
||||
std::filesystem::create_directories(hex::getPath(ImHexPath::Patterns)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(ImHexPath::PatternsInclude)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(ImHexPath::Magic)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(ImHexPath::Plugins)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(ImHexPath::Resources)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(ImHexPath::Config)[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadDefaultViews() {
|
||||
|
||||
ContentRegistry::Views::add<ViewHexEditor>();
|
||||
ContentRegistry::Views::add<ViewPattern>();
|
||||
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>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool deleteViews() {
|
||||
for (auto &view : SharedData::views)
|
||||
delete view;
|
||||
SharedData::views.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadPlugins() {
|
||||
for (const auto &dir : hex::getPath(ImHexPath::Plugins)) {
|
||||
PluginManager::load(dir);
|
||||
}
|
||||
|
||||
if (PluginManager::getPlugins().empty()) {
|
||||
getInitArguments().push_back({ "no-plugins", { } });
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto &plugin : PluginManager::getPlugins()) {
|
||||
plugin.initializePlugin();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool unloadPlugins() {
|
||||
PluginManager::unload();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadSettings() {
|
||||
ContentRegistry::Settings::load();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool storeSettings() {
|
||||
ContentRegistry::Settings::store();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Task> getInitTasks() {
|
||||
return {
|
||||
{ "Checking for updates...", checkForUpdates },
|
||||
{ "Creating directories...", createDirectories },
|
||||
{ "Loading default views...", loadDefaultViews },
|
||||
{ "Loading plugins...", loadPlugins },
|
||||
{ "Loading settings...", loadSettings }
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<Task> getExitTasks() {
|
||||
return {
|
||||
{ "Unloading plugins...", unloadPlugins },
|
||||
{ "Saving settings...", storeSettings },
|
||||
{ "Cleaning up views...", deleteViews }
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<Argument>& getInitArguments() {
|
||||
static std::vector<Argument> initArguments;
|
||||
|
||||
return initArguments;
|
||||
}
|
||||
|
||||
}
|
@ -2,61 +2,47 @@
|
||||
|
||||
#include "window.hpp"
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
#include <hex/lang/pattern_data.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include "init/splash_window.hpp"
|
||||
#include "init/tasks.hpp"
|
||||
|
||||
#include "views/view_hexeditor.hpp"
|
||||
#include "views/view_pattern.hpp"
|
||||
#include "views/view_pattern_data.hpp"
|
||||
#include "views/view_hashes.hpp"
|
||||
#include "views/view_information.hpp"
|
||||
#include "views/view_help.hpp"
|
||||
#include "views/view_tools.hpp"
|
||||
#include "views/view_strings.hpp"
|
||||
#include "views/view_data_inspector.hpp"
|
||||
#include "views/view_disassembler.hpp"
|
||||
#include "views/view_bookmarks.hpp"
|
||||
#include "views/view_patches.hpp"
|
||||
#include "views/view_command_palette.hpp"
|
||||
#include "views/view_settings.hpp"
|
||||
#include "views/view_data_processor.hpp"
|
||||
#include "views/view_yara.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
using namespace hex;
|
||||
|
||||
Window window(argc, argv);
|
||||
// Initialization
|
||||
{
|
||||
init::WindowSplash splashWindow(argc, argv);
|
||||
|
||||
// Shared Data
|
||||
std::vector<lang::PatternData*> patternData;
|
||||
for (const auto &[name, task] : init::getInitTasks())
|
||||
splashWindow.addStartupTask(name, task);
|
||||
|
||||
// Create views
|
||||
ContentRegistry::Views::add<ViewHexEditor>(patternData);
|
||||
ContentRegistry::Views::add<ViewPattern>(patternData);
|
||||
ContentRegistry::Views::add<ViewPatternData>(patternData);
|
||||
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>();
|
||||
if (!splashWindow.loop())
|
||||
init::getInitArguments().push_back({ "tasks-failed", { } });
|
||||
}
|
||||
|
||||
if (argc > 2)
|
||||
// Clean up
|
||||
ON_SCOPE_EXIT {
|
||||
for (const auto &[name, task] : init::getExitTasks())
|
||||
task();
|
||||
};
|
||||
|
||||
// Main window
|
||||
{
|
||||
Window window;
|
||||
|
||||
if (argc == 1)
|
||||
; // No arguments provided
|
||||
else if (argc == 2)
|
||||
EventManager::post<EventFileDropped>(argv[1]);
|
||||
else {
|
||||
hex::log::fatal("Usage: imhex [file_name]");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
hex::log::info("Welcome to ImHex!");
|
||||
|
||||
window.loop();
|
||||
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -18,8 +18,7 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
ViewHexEditor::ViewHexEditor(std::vector<lang::PatternData*> &patternData)
|
||||
: View("hex.view.hexeditor.name"_lang), m_patternData(patternData) {
|
||||
ViewHexEditor::ViewHexEditor() : View("hex.view.hexeditor.name"_lang) {
|
||||
|
||||
this->m_searchStringBuffer.resize(0xFFF, 0x00);
|
||||
this->m_searchHexBuffer.resize(0xFFF, 0x00);
|
||||
@ -162,7 +161,7 @@ namespace hex {
|
||||
EventManager::subscribe<EventPatternChanged>(this, [this]() {
|
||||
this->m_highlightedBytes.clear();
|
||||
|
||||
for (const auto &pattern : this->m_patternData)
|
||||
for (const auto &pattern : SharedData::patternData)
|
||||
this->m_highlightedBytes.merge(pattern->getHighlightedAddresses());
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
ViewPattern::ViewPattern(std::vector<lang::PatternData*> &patternData) : View("hex.view.pattern.name"), m_patternData(patternData) {
|
||||
ViewPattern::ViewPattern() : View("hex.view.pattern.name") {
|
||||
this->m_patternLanguageRuntime = new lang::PatternLanguage();
|
||||
|
||||
this->m_textEditor.SetLanguageDefinition(PatternLanguage());
|
||||
@ -345,10 +345,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
void ViewPattern::clearPatternData() {
|
||||
for (auto &data : this->m_patternData)
|
||||
for (auto &data : SharedData::patternData)
|
||||
delete data;
|
||||
|
||||
this->m_patternData.clear();
|
||||
SharedData::patternData.clear();
|
||||
lang::PatternData::resetPalette();
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ namespace hex {
|
||||
this->m_console = this->m_patternLanguageRuntime->getConsoleLog();
|
||||
|
||||
if (result.has_value()) {
|
||||
this->m_patternData = std::move(result.value());
|
||||
SharedData::patternData = std::move(result.value());
|
||||
View::doLater([]{
|
||||
EventManager::post<EventPatternChanged>();
|
||||
});
|
||||
|
@ -5,8 +5,7 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
ViewPatternData::ViewPatternData(std::vector<lang::PatternData*> &patternData)
|
||||
: View("hex.view.pattern_data.name"), m_patternData(patternData) {
|
||||
ViewPatternData::ViewPatternData() : View("hex.view.pattern_data.name") {
|
||||
|
||||
EventManager::subscribe<EventPatternChanged>(this, [this]() {
|
||||
this->m_sortedPatternData.clear();
|
||||
@ -53,7 +52,7 @@ namespace hex {
|
||||
auto provider = SharedData::currentProvider;
|
||||
if (provider != nullptr && provider->isReadable()) {
|
||||
|
||||
if (beginPatternDataTable(provider, this->m_patternData, this->m_sortedPatternData)) {
|
||||
if (beginPatternDataTable(provider, SharedData::patternData, this->m_sortedPatternData)) {
|
||||
ImGui::TableHeadersRow();
|
||||
if (this->m_sortedPatternData.size() > 0) {
|
||||
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
#include <fontawesome_font.h>
|
||||
|
||||
#include "helpers/plugin_handler.hpp"
|
||||
#include "helpers/plugin_manager.hpp"
|
||||
#include "init/tasks.hpp"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@ -53,64 +54,19 @@ namespace hex {
|
||||
buf->append("\n");
|
||||
}
|
||||
|
||||
Window::Window(int &argc, char **&argv) {
|
||||
SharedData::mainArgc = argc;
|
||||
SharedData::mainArgv = argv;
|
||||
Window::Window() {
|
||||
SharedData::currentProvider = nullptr;
|
||||
|
||||
#if defined(RELEASE)
|
||||
#if !defined(RELEASE)
|
||||
{
|
||||
if (argc < 2) {
|
||||
View::showFatalPopup("No launch arguments supplied! Please launch imhex instead of imhexg!");
|
||||
}
|
||||
|
||||
std::string launchArguments = argv[argc - 1];
|
||||
|
||||
if (launchArguments.find("--args=") != 0) {
|
||||
View::showFatalPopup("No launch arguments supplied! Please launch imhex instead of imhexg!");
|
||||
}
|
||||
|
||||
bool commitChecked = false;
|
||||
bool branchChecked = false;
|
||||
|
||||
for (const auto& arg : hex::splitString(launchArguments.substr(7), "|")) {
|
||||
auto splitArg = hex::splitString(arg, "=");
|
||||
|
||||
// Handle flags
|
||||
if (splitArg.size() == 1) {
|
||||
auto &flag = splitArg[0];
|
||||
|
||||
if (flag == "tasks-failed") {
|
||||
|
||||
} else if (flag == "splash-skipped") {
|
||||
|
||||
}
|
||||
}
|
||||
// Handle arguments
|
||||
else if (splitArg.size() == 2) {
|
||||
auto &name = splitArg[0];
|
||||
auto &value = splitArg[1];
|
||||
|
||||
if (name == "git-hash") {
|
||||
if (value != GIT_COMMIT_HASH)
|
||||
View::showFatalPopup("Launcher and ImHex version commit mismatch. Please fully update ImHex before using it!");
|
||||
commitChecked = true;
|
||||
} else if (name == "git-branch") {
|
||||
if (value != GIT_BRANCH)
|
||||
View::showFatalPopup("Launcher and ImHex version branch mismatch. Please fully update ImHex before using it!");
|
||||
branchChecked = true;
|
||||
} else if (name == "update") {
|
||||
for (const auto &[argument, value] : init::getInitArguments()) {
|
||||
if (argument == "update-available") {
|
||||
this->m_availableUpdate = value;
|
||||
} else if (argument == "no-plugins") {
|
||||
View::showErrorPopup("No plugins are loaded, including the built-in functions plugin!\n"
|
||||
"Make sure you got at least builtin.hexplug in your plugins folder.");
|
||||
}
|
||||
}
|
||||
// Handle others
|
||||
else {
|
||||
View::showFatalPopup("Invalid launch arguments supplied! Please launch imhex instead of imhexg!");
|
||||
}
|
||||
}
|
||||
|
||||
if (!commitChecked || !branchChecked)
|
||||
View::showFatalPopup("No commit information available! Please launch imhex instead of imhexg!");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -207,9 +163,6 @@ namespace hex {
|
||||
glfwSetWindowTitle(this->m_window, ("ImHex - " + windowTitle).c_str());
|
||||
});
|
||||
|
||||
this->initPlugins();
|
||||
|
||||
ContentRegistry::Settings::load();
|
||||
EventManager::post<EventSettingsChanged>();
|
||||
|
||||
for (const auto &path : ContentRegistry::Settings::read("hex.builtin.setting.imhex", "hex.builtin.setting.imhex.recent_files"))
|
||||
@ -221,13 +174,6 @@ namespace hex {
|
||||
|
||||
this->deinitImGui();
|
||||
this->deinitGLFW();
|
||||
ContentRegistry::Settings::store();
|
||||
|
||||
for (auto &view : SharedData::views)
|
||||
delete view;
|
||||
SharedData::views.clear();
|
||||
|
||||
this->deinitPlugins();
|
||||
|
||||
EventManager::unsubscribe<EventSettingsChanged>(this);
|
||||
EventManager::unsubscribe<EventFileLoaded>(this);
|
||||
@ -236,7 +182,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void Window::loop() {
|
||||
bool pressedKeys[512] = { 0 };
|
||||
bool pressedKeys[512] = { false };
|
||||
|
||||
this->m_lastFrameTime = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(this->m_window)) {
|
||||
@ -513,7 +459,7 @@ namespace hex {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.welcome.header.plugins"_lang);
|
||||
{
|
||||
const auto &plugins = PluginHandler::getPlugins();
|
||||
const auto &plugins = PluginManager::getPlugins();
|
||||
|
||||
if (plugins.empty()) {
|
||||
// Intentionally left untranslated so it will be readable even if no plugin with translations is loaded
|
||||
@ -817,20 +763,6 @@ namespace hex {
|
||||
ImGui_ImplOpenGL3_Init("#version 150");
|
||||
}
|
||||
|
||||
void Window::initPlugins() {
|
||||
for (const auto &dir : hex::getPath(ImHexPath::Plugins)) {
|
||||
try {
|
||||
PluginHandler::load(dir);
|
||||
} catch (std::runtime_error &e) {
|
||||
// Plugin folder not found. Not a problem.
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &plugin : PluginHandler::getPlugins()) {
|
||||
plugin.initializePlugin();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::deinitGLFW() {
|
||||
glfwDestroyWindow(this->m_window);
|
||||
glfwTerminate();
|
||||
@ -845,8 +777,4 @@ namespace hex {
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
void Window::deinitPlugins() {
|
||||
PluginHandler::unload();
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
include("${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake")
|
||||
include("${CMAKE_SOURCE_DIR}/cmake/modules/PostprocessBundle.cmake")
|
||||
|
||||
get_target_property(IMHEX_VERSION imhex VERSION)
|
||||
project(splash VERSION ${IMHEX_VERSION})
|
||||
|
||||
addVersionDefines()
|
||||
configurePackageCreation()
|
||||
|
||||
if (WIN32)
|
||||
set(application_type "WIN32")
|
||||
else ()
|
||||
set(application_type)
|
||||
endif ()
|
||||
|
||||
add_executable(splash ${application_type}
|
||||
source/main.cpp
|
||||
source/splash_window.cpp
|
||||
${imhex_icon}
|
||||
)
|
||||
|
||||
target_include_directories(splash PUBLIC include)
|
||||
|
||||
add_compile_definitions(IMHEX_FILE_NAME=\"$<TARGET_FILE_NAME:imhex>\")
|
||||
set_target_properties(splash PROPERTIES OUTPUT_NAME "imhex")
|
||||
add_dependencies(splash imhex)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(splash libimhex winpthread)
|
||||
else ()
|
||||
target_link_libraries(splash libimhex pthread)
|
||||
endif ()
|
@ -1,94 +0,0 @@
|
||||
#include <hex.hpp>
|
||||
|
||||
#include "splash_window.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr auto ImHexPath = IMHEX_FILE_NAME;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
bool skipSplash = false;
|
||||
std::string fileToOpen;
|
||||
std::vector<std::string> imHexArgs;
|
||||
|
||||
// Handle command line arguments
|
||||
{
|
||||
if (argc == 1) {
|
||||
// No optional arguments used, use default
|
||||
} else if (argc == 2) {
|
||||
if (argv[1] == std::string("--no-splash")) skipSplash = true;
|
||||
else fileToOpen = argv[1];
|
||||
} else if (argc == 3) {
|
||||
fileToOpen = argv[1];
|
||||
|
||||
if (argv[2] == std::string("--no-splash")) skipSplash = true;
|
||||
else {
|
||||
printf("Invalid argument '%s'\n", argv[2]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
printf("Usage: imhex [file_path] [--no-splash] ");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
imHexArgs.emplace_back("git-hash=" GIT_COMMIT_HASH);
|
||||
imHexArgs.emplace_back("git-branch=" GIT_BRANCH);
|
||||
|
||||
if (!skipSplash) {
|
||||
hex::pre::WindowSplash window;
|
||||
|
||||
window.addStartupTask("Checking for updates...", [&]{
|
||||
hex::Net net;
|
||||
|
||||
auto releases = net.getJson("https://api.github.com/repos/WerWolv/ImHex/releases/latest");
|
||||
if (releases.code != 200)
|
||||
return false;
|
||||
|
||||
if (!releases.response.contains("tag_name") || !releases.response["tag_name"].is_string())
|
||||
return false;
|
||||
|
||||
auto currVersion = "v" + std::string(IMHEX_VERSION).substr(0, 5);
|
||||
auto latestVersion = releases.response["tag_name"].get<std::string_view>();
|
||||
|
||||
if (latestVersion != currVersion)
|
||||
imHexArgs.push_back(std::string("update=") + latestVersion.data());
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
window.addStartupTask("Creating directories...", []{
|
||||
std::filesystem::create_directories(hex::getPath(hex::ImHexPath::Patterns)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(hex::ImHexPath::PatternsInclude)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(hex::ImHexPath::Magic)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(hex::ImHexPath::Plugins)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(hex::ImHexPath::Resources)[0]);
|
||||
std::filesystem::create_directories(hex::getPath(hex::ImHexPath::Config)[0]);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!window.loop())
|
||||
imHexArgs.emplace_back("tasks-failed");
|
||||
|
||||
} else {
|
||||
imHexArgs.emplace_back("splash-skipped");
|
||||
}
|
||||
|
||||
// Launch ImHex
|
||||
std::string packedArgs = "--args=" + hex::combineStrings(imHexArgs, "|");
|
||||
|
||||
if (fileToOpen.empty())
|
||||
return execl(ImHexPath, ImHexPath, packedArgs.c_str(), nullptr);
|
||||
else
|
||||
return execl(ImHexPath, ImHexPath, fileToOpen.c_str(), packedArgs.c_str(), nullptr);
|
||||
}
|
Loading…
Reference in New Issue
Block a user