diff --git a/.gitmodules b/.gitmodules index 307f957..262cf0a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,6 @@ [submodule "libs/zephyrus"] path = libs/zephyrus url = https://github.com/Prevter/Zephyrus +[submodule "libs/sinaps"] + path = libs/sinaps + url = https://github.com/prevter/sinaps diff --git a/CMakeLists.txt b/CMakeLists.txt index de29293..f993216 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,17 +67,28 @@ target_include_directories( ${PROJECT_NAME} INTERFACE ${CMAKE_BINARY_DIR} - libs/glew/include ) target_link_libraries( ${PROJECT_NAME} INTERFACE external_libs - opengl32 - ${CMAKE_SOURCE_DIR}/libs/glew/lib/Release/Win32/glew32.lib ) +if (WIN32) + # Add GLEW for Windows + target_include_directories( + ${PROJECT_NAME} + INTERFACE + libs/glew/include + ) + target_link_libraries( + ${PROJECT_NAME} + INTERFACE + ${CMAKE_SOURCE_DIR}/libs/glew/lib/Release/Win32/glew32.lib + ) +endif () + if (PROJECT_IS_TOP_LEVEL) target_compile_definitions(${PROJECT_NAME} INTERFACE OPENHACK_EXPORT) endif() diff --git a/api/openhack.hpp b/api/openhack.hpp index 9692d5b..55cfc17 100644 --- a/api/openhack.hpp +++ b/api/openhack.hpp @@ -3,11 +3,15 @@ #include #include +#ifdef WIN32 #if OPENHACK_EXPORT #define OPENHACK_DLL __declspec(dllexport) #else #define OPENHACK_DLL __declspec(dllimport) #endif +#else +#define OPENHACK_DLL +#endif #ifdef GEODE_IS_WINDOWS #define LOG_ERROR(message) geode::log::error(message) diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 7b8fbfe..e21915f 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -29,16 +29,11 @@ target_include_directories( imgui/backends ) -target_link_libraries( - imgui PUBLIC - opengl32 -) - # Other libraries -add_subdirectory(gd.hpp) add_subdirectory(json) -add_subdirectory(discord-rpc) add_subdirectory(zephyrus) +add_subdirectory(gd.hpp) +add_subdirectory(sinaps) # Link all external libraries target_link_libraries( @@ -46,15 +41,18 @@ target_link_libraries( imgui gd.hpp nlohmann_json::nlohmann_json - discord-rpc Zephyrus + sinaps ) if (WIN32) # GLFW add_subdirectory(glfw) + add_subdirectory(discord-rpc) + target_link_libraries( external_libs INTERFACE glfw + discord-rpc ) endif() \ No newline at end of file diff --git a/libs/gd.hpp b/libs/gd.hpp index c4a01b3..145d8de 160000 --- a/libs/gd.hpp +++ b/libs/gd.hpp @@ -1 +1 @@ -Subproject commit c4a01b31da05ade279bec068b29d0c6811b67b80 +Subproject commit 145d8de6e99ad722c231ed251eeab3a156e6a2b6 diff --git a/libs/sinaps b/libs/sinaps new file mode 160000 index 0000000..5c04f82 --- /dev/null +++ b/libs/sinaps @@ -0,0 +1 @@ +Subproject commit 5c04f82cbed7abfdbb9174362d35b33fa3f82916 diff --git a/src/geode/hooks/GJBaseGameLayer.cpp b/src/geode/hooks/GJBaseGameLayer.cpp index 13cf297..4e312eb 100644 --- a/src/geode/hooks/GJBaseGameLayer.cpp +++ b/src/geode/hooks/GJBaseGameLayer.cpp @@ -14,7 +14,7 @@ namespace openhack::hooks::GJBaseGameLayerHook { hacks::NoclipLimit::processCommands(); reinterpret_cast(self)->processCommands(); hacks::Hitboxes::processCommands(); - hacks::Zephyrus::GJBaseGameLayerProcessCommands(); + ON_WINDOWS(hacks::Zephyrus::GJBaseGameLayerProcessCommands();) } } @@ -22,9 +22,10 @@ namespace openhack::hooks { struct GJBaseGameLayerHook2 : geode::Modify { void update(float dt) { hacks::FrameStepper::gameUpdate(&dt); - hacks::Display::schedulerUpdate(dt, [&](float dt) { + ON_WINDOWS(hacks::Display::schedulerUpdate(dt, [&](float dt) { GJBaseGameLayer::update(dt); - }); + });) + ON_ANDROID(GJBaseGameLayer::update(dt);) } }; } diff --git a/src/geode/hooks/MainGameLayer.cpp b/src/geode/hooks/MainGameLayer.cpp index 6763689..38609ae 100644 --- a/src/geode/hooks/MainGameLayer.cpp +++ b/src/geode/hooks/MainGameLayer.cpp @@ -12,7 +12,7 @@ namespace openhack::hooks::MenuGameLayerHook { struct MenuGameLayerHook2 : geode::Modify { void update(float dt) { - hacks::MenuGameplay::menuUpdate(reinterpret_cast(m_playerObject)); + // hacks::MenuGameplay::menuUpdate(reinterpret_cast(m_playerObject)); MenuGameLayer::update(dt); } }; diff --git a/src/geode/hooks/PlayLayer.cpp b/src/geode/hooks/PlayLayer.cpp index b3a6fb8..54eb671 100644 --- a/src/geode/hooks/PlayLayer.cpp +++ b/src/geode/hooks/PlayLayer.cpp @@ -42,7 +42,7 @@ namespace openhack::hooks { hacks::AutoPickupCoins::resetLevel(); hacks::StartPosSwitcher::resetLevel(); config::setGlobal("fromPercent", getCurrentPercentInt()); - hacks::Zephyrus::PlayLayerResetLevel(); + ON_WINDOWS(hacks::Zephyrus::PlayLayerResetLevel();) hacks::RandomSeed::resetLevel(); } @@ -72,12 +72,12 @@ namespace openhack::hooks { } void playEndAnimationToPos(cocos2d::CCPoint pos) { - hacks::Zephyrus::endAnimation(); + ON_WINDOWS(hacks::Zephyrus::endAnimation();) PlayLayer::playEndAnimationToPos(pos); } void playPlatformerEndAnimationToPos(cocos2d::CCPoint pos, bool unk) { - hacks::Zephyrus::endAnimation(); + ON_WINDOWS(hacks::Zephyrus::endAnimation();) PlayLayer::playPlatformerEndAnimationToPos(pos, unk); } diff --git a/src/geode/hooks/PlayerObject.cpp b/src/geode/hooks/PlayerObject.cpp index 1b1f5b1..ca334de 100644 --- a/src/geode/hooks/PlayerObject.cpp +++ b/src/geode/hooks/PlayerObject.cpp @@ -7,13 +7,13 @@ namespace openhack::hooks { struct PlayerObjectHook : geode::Modify { void pushButton(PlayerButton btn) { - hacks::Zephyrus::PlayerObjectPushButton(reinterpret_cast(this), static_cast(btn)); + ON_WINDOWS(hacks::Zephyrus::PlayerObjectPushButton(reinterpret_cast(this), static_cast(btn));) hacks::Labels::pushButton(reinterpret_cast(this)); PlayerObject::pushButton(btn); } void releaseButton(PlayerButton btn) { - hacks::Zephyrus::PlayerObjectReleaseButton(reinterpret_cast(this), static_cast(btn)); + ON_WINDOWS(hacks::Zephyrus::PlayerObjectReleaseButton(reinterpret_cast(this), static_cast(btn));) hacks::Labels::releaseButton(reinterpret_cast(this)); PlayerObject::releaseButton(btn); } diff --git a/src/shared/gui/color.hpp b/src/shared/gui/color.hpp index 388040a..26ab0ca 100644 --- a/src/shared/gui/color.hpp +++ b/src/shared/gui/color.hpp @@ -105,7 +105,11 @@ namespace openhack::gui { /// @return New color static Color fromString(const char *color) { uint32_t c; +#ifdef WIN32 sscanf_s(color, "%X", &c); +#else + sscanf(color, "%X", &c); +#endif return fromInt(c); } diff --git a/src/shared/gui/gui.cpp b/src/shared/gui/gui.cpp index e70a6f8..6d86d1a 100644 --- a/src/shared/gui/gui.cpp +++ b/src/shared/gui/gui.cpp @@ -55,7 +55,7 @@ namespace openhack::gui { } void init() { - utils::resetWindowHandle(); + ON_WINDOWS(utils::resetWindowHandle();) // Load all fonts from "OPENHACK_DIRECTORY/fonts/" auto fontDir = utils::getModFontsDirectory(); diff --git a/src/shared/hacks/auto-deafen/auto-deafen.cpp b/src/shared/hacks/auto-deafen/auto-deafen.cpp index d2bee4c..a5b197f 100644 --- a/src/shared/hacks/auto-deafen/auto-deafen.cpp +++ b/src/shared/hacks/auto-deafen/auto-deafen.cpp @@ -1,6 +1,7 @@ #include "auto-deafen.hpp" #include "../../menu/menu.hpp" +#ifdef PLATFORM_WINDOWS #include "../accurate-percentage/accurate-percentage.hpp" namespace openhack::hacks { @@ -80,4 +81,5 @@ namespace openhack::hacks { setState(percentage >= startPercentage && percentage <= endPercentage); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/shared/hacks/discord-rpc/discord-rpc.cpp b/src/shared/hacks/discord-rpc/discord-rpc.cpp index ac27163..da826de 100644 --- a/src/shared/hacks/discord-rpc/discord-rpc.cpp +++ b/src/shared/hacks/discord-rpc/discord-rpc.cpp @@ -1,6 +1,7 @@ #include "discord-rpc.hpp" #include "../../menu/menu.hpp" #include "../labels/labels.hpp" +#ifdef PLATFORM_WINDOWS #include @@ -287,4 +288,5 @@ namespace openhack::hacks { Discord_UpdatePresence(&presence); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/shared/hacks/display/display.cpp b/src/shared/hacks/display/display.cpp index 0fe6b3d..3a1e903 100644 --- a/src/shared/hacks/display/display.cpp +++ b/src/shared/hacks/display/display.cpp @@ -6,16 +6,16 @@ namespace openhack::hacks { static ToggleComponent* s_fpsLimitBypass = nullptr; void Display::onInit() { - config::setGlobal("physicsTickAddr", gd::sigscan::findPattern("8988883B")); + config::setGlobal("physicsTickAddr", sinaps::find("8988883B")); config::setIfEmpty("hack.display.tps", 240.0f); config::setIfEmpty("hack.display.tps_bypass", false); // Patch to remove minimum 60 FPS limit - auto match = gd::sigscan::match("0F2F05????^762AFF15", "9090"); - if (match.empty()) - L_WARN("Failed to find signature for Display"); + auto match = sinaps::match("0F2F05????^762AFF15", "9090"); + if (match.isErr()) + L_WARN("Failed to find signature for Display: {}", match.err()); else - s_fpsLimitBypass = new ToggleComponent("", "", match); + s_fpsLimitBypass = new ToggleComponent("", "", { match.val() }); // Create window menu::addWindow("Display", [&]() { diff --git a/src/shared/hacks/hack-list.hpp b/src/shared/hacks/hack-list.hpp index 9716706..ed08957 100644 --- a/src/shared/hacks/hack-list.hpp +++ b/src/shared/hacks/hack-list.hpp @@ -33,24 +33,24 @@ namespace openhack::hacks { /// @brief List of all hacks. static std::vector s_allHacks = { new SpeedHack(), - new Display(), + ON_WINDOWS(new Display(),) new Shortcuts(), new AutoSafemode(), new InstantComplete(), new AutoPickupCoins(), new StartPosSwitcher(), - new DiscordRPC(), + ON_WINDOWS(new DiscordRPC(),) new ClickTeleport(), new Labels(), new NoclipLimit(), new RGBIcons(), - new Zephyrus(), + ON_WINDOWS(new Zephyrus(),) new FrameStepper(), new RandomSeed(), new MenuGameplay(), new Hitboxes(), new RespawnDelay(), - new AutoDeafen(), + ON_WINDOWS(new AutoDeafen(),) new SmartStartPos(), new AutoKill(), new AutoSave(), diff --git a/src/shared/hacks/hacks.cpp b/src/shared/hacks/hacks.cpp index 106a4ac..efc643c 100644 --- a/src/shared/hacks/hacks.cpp +++ b/src/shared/hacks/hacks.cpp @@ -1,6 +1,5 @@ #include "hacks.hpp" #include "../openhack.hpp" -#include #include "hack-list.hpp" namespace openhack::hacks { @@ -67,7 +66,7 @@ namespace openhack::hacks { static std::vector hacks; /// @brief Read an opcode from a JSON object - gd::sigscan::Opcode readOpcode(const nlohmann::json &opcode) { + sinaps::patch_t readOpcode(const nlohmann::json &opcode) { auto addrStr = opcode.at("addr").get(); auto onStr = opcode.at("on").get(); auto offStr = opcode.at("off").get(); @@ -80,10 +79,19 @@ namespace openhack::hacks { library = opcode.at("lib").get(); } - return {utils::hexToAddr(addrStr), library, off, on}; + auto offset = utils::hexToAddr(addrStr); + + auto base = utils::getModuleHandle(library.c_str()); + void* address = reinterpret_cast(base + offset); + + sinaps::patch_t patch(address, off, on); + patch.module = library; + patch.offset = offset; + + return patch; } - using Opcodes = std::vector; + using Opcodes = std::vector; using MaskMap = std::unordered_map; using PatternMap = std::unordered_map; @@ -183,10 +191,10 @@ namespace openhack::hacks { nlohmann::json opcodeList; for (const auto &opcode: opcodes) { nlohmann::json opcodeJson; - opcodeJson["addr"] = fmt::format("0x{:X}", opcode.address); - opcodeJson["on"] = utils::bytesToHex(opcode.patched); + opcodeJson["addr"] = fmt::format("0x{:X}", (uintptr_t) opcode.address); + opcodeJson["on"] = utils::bytesToHex(opcode.patch); opcodeJson["off"] = utils::bytesToHex(opcode.original); - opcodeJson["lib"] = opcode.library; + opcodeJson["lib"] = opcode.module; opcodeList.push_back(opcodeJson); } maskMap[mask] = opcodeList; @@ -231,7 +239,7 @@ namespace openhack::hacks { PatternMap cache = tryGetCache(title); PatternMap newCache; - L_BENCHMARK(title, + //L_BENCHMARK(title, for (const auto &component: json.at("items")) { if (component.contains("version")) { auto version = component.at("version").get(); @@ -246,7 +254,7 @@ namespace openhack::hacks { } else if (type == "toggle") { auto toggleTitle = component.at("title").get(); auto id = component.at("id").get(); - std::vector opcodes; + std::vector opcodes; bool warn = false; for (const auto &opcode: component.at("opcodes")) { if (opcode.contains("version")) { @@ -283,7 +291,7 @@ namespace openhack::hacks { if (!found || !verified) { // Scan for the addresses - opc = gd::sigscan::match(pattern, mask, library); + opc = sinaps::matchAll(pattern, mask, utils::getModule(library)); if (opc.empty()) { warn = true; break; @@ -345,7 +353,7 @@ namespace openhack::hacks { } } } - ); + //); // Sort the components std::sort(windowComponents.begin(), windowComponents.end(), [](const auto &a, const auto &b) { @@ -405,30 +413,12 @@ namespace openhack::hacks { return s_allHacks; } - bool applyOpcode(const gd::sigscan::Opcode &opcode, bool enable) { - uintptr_t handle; - if (opcode.library.empty()) { - handle = utils::getModuleHandle(); - } else { - handle = utils::getModuleHandle(opcode.library.c_str()); - } - - uintptr_t address = handle + opcode.address; - - std::vector bytes = enable ? opcode.patched : opcode.original; - return utils::patchMemory(address, bytes); + bool applyOpcode(const sinaps::patch_t &opcode, bool enable) { + return opcode.write(enable); } - bool verifyOpcode(const gd::sigscan::Opcode &opcode) { - uintptr_t handle; - if (opcode.library.empty()) { - handle = utils::getModuleHandle(); - } else { - handle = utils::getModuleHandle(opcode.library.c_str()); - } - - uintptr_t address = handle + opcode.address; - + bool verifyOpcode(const sinaps::patch_t &opcode) { + auto address = reinterpret_cast(opcode.address); std::vector bytes = utils::readMemory(address, opcode.original.size()); return bytes == opcode.original; } diff --git a/src/shared/hacks/hacks.hpp b/src/shared/hacks/hacks.hpp index f06a598..0c2db61 100644 --- a/src/shared/hacks/hacks.hpp +++ b/src/shared/hacks/hacks.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include "../gui/gui.hpp" #include "../gui/window.hpp" @@ -47,7 +47,7 @@ namespace openhack::hacks { class ToggleComponent : public Component { public: /// @brief Construct a new Toggle Component object - ToggleComponent(std::string name, std::string id, std::vector opcodes) + ToggleComponent(std::string name, std::string id, std::vector opcodes) : m_name(std::move(name)), m_id(std::move(id)), m_opcodes(std::move(opcodes)) {} /// @brief Loads initial state from the configuration and sets the keybinding if needed @@ -94,7 +94,7 @@ namespace openhack::hacks { std::string m_name; std::string m_description; std::string m_id; - std::vector m_opcodes; + std::vector m_opcodes; bool m_enabled = false; bool m_cheat = false; bool m_hasWarning = false; @@ -161,10 +161,10 @@ namespace openhack::hacks { /// @param opcode The opcode to apply /// @param enable Whether to enable or disable the opcode /// @return True if the opcode was successfully applied - bool applyOpcode(const gd::sigscan::Opcode &opcode, bool enable); + bool applyOpcode(const sinaps::patch_t &opcode, bool enable); /// @brief Verify that the opcode has valid original bytes /// @param opcode The opcode to verify /// @return True if the opcode has valid original bytes - bool verifyOpcode(const gd::sigscan::Opcode &opcode); + bool verifyOpcode(const sinaps::patch_t &opcode); } \ No newline at end of file diff --git a/src/shared/hacks/hitboxes/hitboxes.cpp b/src/shared/hacks/hitboxes/hitboxes.cpp index a5d6f2f..c9c19be 100644 --- a/src/shared/hacks/hitboxes/hitboxes.cpp +++ b/src/shared/hacks/hitboxes/hitboxes.cpp @@ -23,12 +23,14 @@ namespace openhack::hacks { s_hitboxesToggle->applyPatch(enabled); } - inline bool - appendPatch(std::vector &opcodes, const std::string &pattern, const std::string &mask) { - auto patch = gd::sigscan::match(pattern, mask); - if (patch.empty()) return false; + inline bool appendPatch(std::vector &opcodes, const std::string &pattern, const std::string &mask) { + auto patch = sinaps::match(pattern, mask); + if (patch.isErr()) { + L_WARN("Failed to find signature for Hitboxes: {}", patch.err()); + return false; + } - opcodes.insert(opcodes.end(), patch.begin(), patch.end()); + opcodes.push_back(patch.val()); return true; } @@ -83,7 +85,7 @@ namespace openhack::hacks { config::setIfEmpty("hack.hitboxes.other_color", gui::Color(0, 1, 0)); // Initialize the toggle component - std::vector opcodes; + std::vector opcodes; bool success = true; success &= appendPatch(opcodes, "000000740D^80BB??000000", "*0790"); success &= appendPatch(opcodes, "000000^741380BE??000000740A", "9090???????9090"); @@ -91,7 +93,7 @@ namespace openhack::hacks { // Log the addresses of the patches L_INFO("Hitboxes patch addresses:"); for (auto &opcode: opcodes) { - L_TRACE("0x{:X}", opcode.address); + L_TRACE("0x{:X}", (uintptr_t) opcode.address); } } if (!success) return; diff --git a/src/shared/hacks/labels/labels.cpp b/src/shared/hacks/labels/labels.cpp index 8f542d3..9fd893c 100644 --- a/src/shared/hacks/labels/labels.cpp +++ b/src/shared/hacks/labels/labels.cpp @@ -562,8 +562,8 @@ namespace openhack::hacks { }}, {"{clock}", []() { std::time_t now = std::time(nullptr); - std::tm tm{}; - localtime_s(&tm, &now); + ON_WINDOWS(std::tm tm{}; localtime_s(&tm, &now);) + ON_ANDROID(std::tm tm{}; localtime_r(&now, &tm);) return fmt::format("{:02d}:{:02d}:{:02d}", tm.tm_hour, tm.tm_min, tm.tm_sec); }}, {"{fps}", []() { diff --git a/src/shared/hacks/random-seed/random-seed.cpp b/src/shared/hacks/random-seed/random-seed.cpp index 07cb2f1..c891986 100644 --- a/src/shared/hacks/random-seed/random-seed.cpp +++ b/src/shared/hacks/random-seed/random-seed.cpp @@ -21,7 +21,7 @@ namespace openhack::hacks { config::setIfEmpty("hack.random_seed.freeze", false); // Find the seed address from "mov [DWORD PTR ds:?], eax" - uintptr_t movToSeedAddr = gd::sigscan::findPattern("A3^????C783??000000000000C6"); + uintptr_t movToSeedAddr = sinaps::find("A3^????C783??000000000000C6"); if (movToSeedAddr != 0) { s_seedAddr = *reinterpret_cast(movToSeedAddr); if (openhack::debugMode) { diff --git a/src/shared/hacks/respawn-delay/respawn-delay.cpp b/src/shared/hacks/respawn-delay/respawn-delay.cpp index cda02f9..13e1123 100644 --- a/src/shared/hacks/respawn-delay/respawn-delay.cpp +++ b/src/shared/hacks/respawn-delay/respawn-delay.cpp @@ -19,27 +19,27 @@ namespace openhack::hacks { delay = config::get("hack.respawn_delay.delay"); // Initialize toggle - std::vector opcodes = gd::sigscan::match( + auto respawnDelayHook = sinaps::match( "E9????F30F1005^????68????C683", utils::bytesToHex(utils::getBytes((uintptr_t)&delay))); - auto customBypass = gd::sigscan::match("84C0^7410F30F10", "EB"); + auto customBypass = sinaps::match("84C0^7410F30F10", "EB"); - if (openhack::debugMode) { - L_INFO("Respawn Delay patch addresses:"); - for (auto& opcode : opcodes) { - L_TRACE("[Set custom time] 0x{:x}", opcode.address); - } - for (auto& opcode : customBypass) { - L_TRACE("[Bypass 0.5s restart] 0x{:x}", opcode.address); - } + if (respawnDelayHook.isErr()) { + L_WARN("Failed to find signature for RespawnDelay: {}", respawnDelayHook.err()); + return; + } else if (customBypass.isErr()) { + L_WARN("Failed to find signature for RespawnDelay: {}", customBypass.err()); + return; } - if (opcodes.empty() || customBypass.empty()) { - L_WARN("Failed to find signature for RespawnDelay"); - return; + std::vector opcodes = { respawnDelayHook.val(), customBypass.val() }; + + if (openhack::debugMode) { + L_INFO("Respawn Delay patch addresses:"); + L_INFO(" - RespawnDelay: 0x{:X}", (uintptr_t) respawnDelayHook.val().address); + L_INFO(" - CustomBypass: 0x{:X}", (uintptr_t) customBypass.val().address); } - opcodes.push_back(customBypass[0]); s_respawnDelay = new ToggleComponent("", "", opcodes); togglePatch(); diff --git a/src/shared/hacks/shortcuts/shortcuts.cpp b/src/shared/hacks/shortcuts/shortcuts.cpp index d581a0d..adb372f 100644 --- a/src/shared/hacks/shortcuts/shortcuts.cpp +++ b/src/shared/hacks/shortcuts/shortcuts.cpp @@ -125,13 +125,17 @@ namespace openhack::hacks { } void Shortcuts::openResources() { - auto path = utils::getCurrentDirectory() + "/Resources"; - utils::openDirectory(path.c_str()); + ON_WINDOWS( + auto path = utils::getCurrentDirectory() + "/Resources"; + utils::openDirectory(path.c_str()); + ) } void Shortcuts::openAppData() { - auto path = utils::getSaveDirectory(); - utils::openDirectory(path.c_str()); + ON_WINDOWS( + auto path = utils::getSaveDirectory(); + utils::openDirectory(path.c_str()); + ) } void Shortcuts::onInit() { @@ -181,7 +185,6 @@ namespace openhack::hacks { gui::tooltip("DLL injection is not recommended when using Geode."); #else gui::tooltip("Injects a DLL into the game process. Useful for debugging and modding."); -#endif #endif if (gui::button("Resources", {0.5f, 0.f})) @@ -199,6 +202,7 @@ namespace openhack::hacks { menu::keybinds::addMenuKeybind("shortcuts.appdata", "AppData", []() { openAppData(); }); +#endif }); // Initialize keybinds diff --git a/src/shared/hacks/zephyrus/replays.cpp b/src/shared/hacks/zephyrus/replays.cpp index 6c7a4f2..3c975ac 100644 --- a/src/shared/hacks/zephyrus/replays.cpp +++ b/src/shared/hacks/zephyrus/replays.cpp @@ -1,6 +1,6 @@ #include "replays.hpp" #include "../../menu/menu.hpp" - +#ifdef PLATFORM_WINDOWS #ifndef OPENHACK_GEODE #include @@ -196,4 +196,5 @@ namespace openhack::hacks { s_levelFinished = true; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/shared/menu/blur.cpp b/src/shared/menu/blur.cpp index 37d0108..fc3609a 100644 --- a/src/shared/menu/blur.cpp +++ b/src/shared/menu/blur.cpp @@ -1,5 +1,5 @@ #include "blur.hpp" - +#ifdef WIN32 #include #include @@ -98,4 +98,5 @@ namespace openhack::menu::blur { return; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/shared/menu/menu.cpp b/src/shared/menu/menu.cpp index 9cab8dc..f6a45a2 100644 --- a/src/shared/menu/menu.cpp +++ b/src/shared/menu/menu.cpp @@ -398,7 +398,7 @@ namespace openhack::menu { } #endif - utils::resetKeyStates(); + ON_WINDOWS(utils::resetKeyStates();) if (utils::isKeyPressed(config::get("menu.toggleKey", "Tab"))) toggle(); diff --git a/src/shared/openhack.hpp b/src/shared/openhack.hpp index 93a1dca..642280d 100644 --- a/src/shared/openhack.hpp +++ b/src/shared/openhack.hpp @@ -21,18 +21,13 @@ #ifdef OPENHACK_GEODE #include "../geode/pch.hpp" +#define GD_VERSION GEODE_STR(GEODE_GD_VERSION) #include -#define ON_GEODE(...) __VA_ARGS__ -#define ON_STANDALONE(...) - #else #include "../standalone/pch.hpp" -#define ON_GEODE(...) -#define ON_STANDALONE(...) __VA_ARGS__ - #endif /// @brief The namespace for the OpenHack mod. diff --git a/src/shared/platform/android/android.hpp b/src/shared/platform/android/android.hpp index 9a2fb6e..0d99354 100644 --- a/src/shared/platform/android/android.hpp +++ b/src/shared/platform/android/android.hpp @@ -7,5 +7,127 @@ #include #include +#include +#include + namespace openhack::utils { + /// @brief Opens a directory in the file explorer. + /// @param path The path of the directory. + inline void openDirectory(const char *path) { + geode::utils::file::openFolder(path); + } + + /// @brief Opens a URL in the default web browser. + /// @param url The URL to open. + inline void openURL(const std::string& url) { + cocos2d::CCApplication::get()->openURL(url.c_str()); + } + + /// @brief Gets the handle of the module with the given name. + /// @param module The name of the module. + /// @return The handle of the module. + inline uintptr_t getModuleHandle(const char *module = nullptr) { + // if module is nullptr or libcocos2d.dll, return the base address of the game + if (!module || !strcmp(module, "libcocos2d.dll")) { + return geode::base::get(); + } + return 0; + } + + inline sinaps::module_t getModule(const std::string& module) { + uintptr_t base = getModuleHandle(module.c_str()); + if (!base) return {module, 0, 0}; + + struct stat fileStat{}; + if (stat(module.c_str(), &fileStat) == 0) { + return {module, base, static_cast(fileStat.st_size)}; + } + + return {module, base, 0}; + } + + /// @brief Read bytes from the game's memory. + /// @param address The address to read from. + /// @param size The amount of bytes to read. + /// @return The bytes read from the memory. + inline std::vector readMemory(uintptr_t address, size_t size) { + std::vector buffer(size); + memcpy(buffer.data(), (void *) address, size); + return buffer; + } + + /// @return The game version. + inline std::string getGameVersion() { + return GEODE_STR(GEODE_GD_VERSION); + } + + /// @brief Convert a key code to a key name. + /// @param keycode The key code. + /// @return The key name. + inline std::string getKeyName(uint32_t keycode) { + return "Unknown"; + } + + /// @brief Convert a key name to a key code. + /// @param key The key name. + /// @return The key code. + inline uint32_t getKeyCode(std::string key) { + return 0; + } + + /// @brief Check whether a key is down. + inline bool isKeyDown(uint32_t keycode) { + return false; + } + + /// @brief Check whether a key is down. + inline bool isKeyDown(std::string key) { + return isKeyDown(getKeyCode(std::move(key))); + } + + /// @brief Check whether a key was pressed during the current frame. + /// @param keycode The key code. + /// @return True if the key was pressed. + inline bool isKeyPressed(uint32_t keycode) { + return false; + } + + /// @brief Check whether a key was pressed during the current frame. + /// @param key Key name. + /// @return True if the key was pressed. + inline bool isKeyPressed(std::string key) { + return isKeyPressed(getKeyCode(std::move(key))); + } + + /// @brief Check whether a key was released during the current frame. + /// @param keycode The key code. + /// @return True if the key was released. + inline bool isKeyReleased(uint32_t keycode) { + return false; + } + + /// @brief Check whether a key was released during the current frame. + /// @param key Key name. + /// @return True if the key was released. + inline bool isKeyReleased(std::string key) { + return isKeyReleased(getKeyCode(std::move(key))); + } + + /// @brief Write bytes to the game's memory. + /// @param address The address to write to. + /// @param bytes The bytes to write. + /// @return True if the bytes were successfully written. + inline bool patchMemory(uintptr_t address, const std::vector &bytes) { + return sinaps::mem::write(reinterpret_cast(address), bytes.data(), bytes.size()); + } + + /// @brief Write a value to the game's memory. + /// @tparam T The type of the value. + /// @param address The address to write to. + /// @param value The value to write. + /// @return True if the value was successfully written. + template + inline bool writeMemory(uintptr_t address, T value) { + return patchMemory(address, std::vector((uint8_t *) &value, (uint8_t *) &value + sizeof(T))); + } } \ No newline at end of file diff --git a/src/shared/platform/win32/win32.hpp b/src/shared/platform/win32/win32.hpp index de1b968..b11e21a 100644 --- a/src/shared/platform/win32/win32.hpp +++ b/src/shared/platform/win32/win32.hpp @@ -54,6 +54,17 @@ namespace openhack::utils { return reinterpret_cast(GetModuleHandleA(module)); } + inline sinaps::module_t getModule(const std::string& module) { + uintptr_t base = getModuleHandle(module.c_str()); + uintptr_t size = 0; + if (base) { + auto dosHeader = reinterpret_cast(base); + auto ntHeaders = reinterpret_cast(base + dosHeader->e_lfanew); + size = ntHeaders->OptionalHeader.SizeOfImage; + } + return {module, base, size}; + } + /// @brief Write bytes to the game's memory. /// @param address The address to write to. /// @param bytes The bytes to write. diff --git a/src/shared/utils.hpp b/src/shared/utils.hpp index 398e6ef..61ffadf 100644 --- a/src/shared/utils.hpp +++ b/src/shared/utils.hpp @@ -32,6 +32,18 @@ #define L_BENCHMARK(name, code) code #endif +#ifdef OPENHACK_GEODE + +#define ON_GEODE(...) __VA_ARGS__ +#define ON_STANDALONE(...) + +#else + +#define ON_GEODE(...) +#define ON_STANDALONE(...) __VA_ARGS__ + +#endif + namespace openhack::utils { /// @brief Generates a random number between min and max. /// @param min The minimum value. @@ -46,7 +58,7 @@ namespace openhack::utils { /// @param max The maximum value. /// @return Random number between min and max. inline float random(float min, float max) { - return min + static_cast (rand()) / (static_cast (RAND_MAX / (max - min))); + return min + static_cast(rand()) / (static_cast((float)RAND_MAX / (max - min))); } /// @brief Generates a random number between min and max. @@ -54,7 +66,7 @@ namespace openhack::utils { /// @param max The maximum value. /// @return Random number between min and max. inline double random(double min, double max) { - return min + static_cast (rand()) / (static_cast (RAND_MAX / (max - min))); + return min + static_cast(rand()) / (static_cast((double)RAND_MAX / (max - min))); } /// @brief Generates a random number between 0 and max. @@ -111,14 +123,15 @@ namespace openhack::utils { /// @brief Converts a screen position to a frame position. /// @param pos The screen position. /// @return The frame position. - inline ImVec2 screenToFrame(const ImVec2& pos) { - auto *director = gd::cocos2d::CCDirector::sharedDirector(); + inline ImVec2 screenToFrame(const ImVec2 &pos) { + ON_STANDALONE(auto *director = gd::cocos2d::CCDirector::sharedDirector();) + ON_GEODE(auto *director = cocos2d::CCDirector::sharedDirector();) const auto frameSize = director->getOpenGLView()->getFrameSize(); const auto winSize = director->getWinSize(); return { - pos.x / frameSize.width * winSize.width, - (1.f - pos.y / frameSize.height) * winSize.height + pos.x / frameSize.width * winSize.width, + (1.f - pos.y / frameSize.height) * winSize.height }; } @@ -244,7 +257,7 @@ namespace openhack::utils { // Convert from hex to byte std::string byteString = hexCopy.substr(index, 2); - uint8_t byte = (uint8_t) strtol(byteString.c_str(), nullptr, 16); + auto byte = (uint8_t) strtol(byteString.c_str(), nullptr, 16); bytes.push_back(byte); index += 2; } @@ -268,7 +281,7 @@ namespace openhack::utils { /// @tparam T The type of the value. /// @param value The value. /// @return The vector of bytes. - template + template inline std::vector getBytes(T value) { return std::vector((uint8_t *) &value, (uint8_t *) &value + sizeof(T)); }