diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index 0a34c7c6..7a1fba6c 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -737,6 +737,7 @@ class cocos2d::CCRenderTexture { static cocos2d::CCRenderTexture* create(int, int, cocos2d::CCTexture2DPixelFormat) = mac 0x35c720; auto newCCImage(bool) = mac 0x35d7d0; auto saveToFile(char const*) = mac 0x35dab0; + auto beginWithClear(float r, float g, float b, float a) = mac 0x35d010; } class cocos2d::CCRepeat { diff --git a/loader/launcher/mac/Bootstrapper.cpp b/loader/launcher/mac/Bootstrapper.cpp index 0fbf8642..1b5c727c 100644 --- a/loader/launcher/mac/Bootstrapper.cpp +++ b/loader/launcher/mac/Bootstrapper.cpp @@ -1,77 +1,4 @@ -#include <ghc/filesystem.hpp> -#include <mach-o/dyld.h> -#include <unistd.h> -#include <dlfcn.h> -#include <array> -#include <iostream> -#include <CoreFoundation/CoreFoundation.h> - -void displayError(std::string alertMessage) { - CFStringRef cfTitle = CFStringCreateWithCString(NULL, "Geode Bootstrapper", kCFStringEncodingUTF8); - CFStringRef cfMessage = CFStringCreateWithCString(NULL, alertMessage.c_str(), kCFStringEncodingUTF8); - - CFUserNotificationDisplayNotice(0, kCFUserNotificationCautionAlertLevel, NULL, NULL, NULL, cfTitle, cfMessage, NULL); -} - -void loadGeode() { - auto dylib = dlopen("Geode.dylib", RTLD_NOW); - if (!dylib) { - displayError(std::string("Couldn't load Geode: ") + dlerror()); - return; - } - auto trigger = dlsym(dylib, "dynamicTrigger"); - if (!trigger) { - displayError(std::string("Couldn't start Geode: ") + dlerror()); - return; - } - reinterpret_cast<void(*)()>(trigger)(); - return; -} - +extern "C" void fake(); __attribute__((constructor)) void _entry() { - std::array<char, PATH_MAX> gddir; - - uint32_t out = PATH_MAX; - _NSGetExecutablePath(gddir.data(), &out); - - ghc::filesystem::path gdpath = gddir.data(); - auto workingDir = gdpath.parent_path().parent_path(); - - auto updatesDir = workingDir / "geode" / "update"; - auto libDir = workingDir / "Frameworks"; - auto resourcesDir = workingDir / "geode" / "resources"; - - auto error = std::error_code(); - - if (ghc::filesystem::exists(updatesDir / "Geode.dylib", error) && !error) { - ghc::filesystem::rename( - updatesDir / "Geode.dylib", - libDir / "Geode.dylib", error - ); - if (error) { - displayError(std::string("Couldn't update Geode: ") + error.message()); - return loadGeode(); - } - } - - if (ghc::filesystem::exists(updatesDir / "resources", error) && !error) { - ghc::filesystem::remove_all(resourcesDir / "geode.loader", error); - - if (error) { - displayError(std::string("Couldn't update Geode resources: ") + error.message()); - return loadGeode(); - } - - ghc::filesystem::rename( - updatesDir / "resources", - resourcesDir / "geode.loader", error - ); - - if (error) { - displayError(std::string("Couldn't update Geode resources: ") + error.message()); - return loadGeode(); - } - } - - return loadGeode(); + fake(); } \ No newline at end of file diff --git a/loader/launcher/mac/CMakeLists.txt b/loader/launcher/mac/CMakeLists.txt index 77c5c678..a2d91df2 100644 --- a/loader/launcher/mac/CMakeLists.txt +++ b/loader/launcher/mac/CMakeLists.txt @@ -10,4 +10,13 @@ set_target_properties(Bootstrapper PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}/nightly" ) -target_link_libraries(Bootstrapper PRIVATE "-framework CoreFoundation" ghc_filesystem) +target_link_libraries(Bootstrapper PRIVATE) + +add_library(FakeGeode SHARED FakeGeode.cpp) +target_compile_features(FakeGeode PUBLIC cxx_std_17) +set_target_properties(FakeGeode PROPERTIES + PREFIX "" + OUTPUT_NAME "Geode" +) + +target_link_libraries(Bootstrapper PRIVATE geode-loader) diff --git a/loader/launcher/mac/FakeGeode.cpp b/loader/launcher/mac/FakeGeode.cpp new file mode 100644 index 00000000..bceb6542 --- /dev/null +++ b/loader/launcher/mac/FakeGeode.cpp @@ -0,0 +1 @@ +extern "C" void fake() {} \ No newline at end of file diff --git a/loader/launcher/mac/Updater.cpp b/loader/launcher/mac/Updater.cpp new file mode 100644 index 00000000..e69de29b diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp index 7edb0b24..57cade24 100644 --- a/loader/src/hooks/MenuLayer.cpp +++ b/loader/src/hooks/MenuLayer.cpp @@ -198,12 +198,7 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> { } void onMissingTextures(CCObject*) { - static bool shownInfoPopup = false; - if (shownInfoPopup) { - return this->onGeode(nullptr); - } - shownInfoPopup = true; - + #ifdef GEODE_IS_DESKTOP try { @@ -218,7 +213,7 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> { "and <cy>unzip its contents</c> into <cb>geode/update/resources</c>.\n" "Afterwards, <cg>restart the game</c>.\n" "You may also continue without installing resources, but be aware that " - "the game <cr>will crash</c>.", + "you won't be able to open <cr>the Geode menu</c>.", "Dismiss", "Open Github", [](auto, bool btn2) { if (btn2) { diff --git a/loader/src/platform/Objcpp.mm b/loader/src/platform/Objcpp.mm index 7e3e9216..8e5d54df 100644 --- a/loader/src/platform/Objcpp.mm +++ b/loader/src/platform/Objcpp.mm @@ -5,6 +5,7 @@ using namespace geode::prelude; #if defined(GEODE_IS_MACOS) +#include "mac/main.mm" #include "mac/crashlog.mm" #include "mac/FileWatcher.mm" #include "mac/util.mm" diff --git a/loader/src/platform/mac/main.cpp b/loader/src/platform/mac/main.cpp deleted file mode 100644 index c5763ecb..00000000 --- a/loader/src/platform/mac/main.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include <Geode/DefaultInclude.hpp> - -#if defined(GEODE_IS_MACOS) - -#include "../load.hpp" -#include <dlfcn.h> -#include <mach-o/dyld.h> -#include <unistd.h> - -#include <thread> - -using namespace geode::prelude; - -std::length_error::~length_error() _NOEXCEPT {} // do not ask... - -// camila has an old ass macos and this function turned -// from dynamic to static thats why she needs to define it -// this is what old versions does to a silly girl - -void dynamicEntry() { - auto dylib = dlopen("GeodeBootstrapper.dylib", RTLD_NOLOAD); - dlclose(dylib); - - auto workingDir = dirs::getGameDir(); - auto libDir = workingDir / "Frameworks"; - auto updatesDir = workingDir / "geode" / "update"; - - auto error = std::error_code(); - - if (ghc::filesystem::exists(updatesDir / "GeodeBootstrapper.dylib", error) && !error) { - ghc::filesystem::rename( - updatesDir / "GeodeBootstrapper.dylib", libDir / "GeodeBootstrapper.dylib", error - ); - if (error) return; - } - - geodeEntry(nullptr); -} - -extern "C" __attribute__((visibility("default"))) void dynamicTrigger() { - std::thread(&dynamicEntry).detach(); -} - -// remove when we can figure out how to not remove it -auto dynamicTriggerRef = &dynamicTrigger; - -#endif \ No newline at end of file diff --git a/loader/src/platform/mac/main.mm b/loader/src/platform/mac/main.mm new file mode 100644 index 00000000..376c7906 --- /dev/null +++ b/loader/src/platform/mac/main.mm @@ -0,0 +1,66 @@ +#include <Geode/DefaultInclude.hpp> + +#if defined(GEODE_IS_MACOS) + +#import <Cocoa/Cocoa.h> +#include "../load.hpp" +#include <dlfcn.h> +#include <mach-o/dyld.h> +#include <unistd.h> +#include <tulip/TulipHook.hpp> +#include <iostream> + +#include <thread> + +using namespace geode::prelude; + +std::length_error::~length_error() _NOEXCEPT {} // do not ask... + +// camila has an old ass macos and this function turned +// from dynamic to static thats why she needs to define it +// this is what old versions does to a silly girl + +extern "C" void fake() {} + +void applicationDidFinishLaunchingHook(void* self, SEL sel, NSNotification* notification) { + // updateGeode(); + + std::array<uint8_t, 6> patchBytes = { + 0x55, + 0x48, 0x89, 0xe5, + 0x41, 0x57 + }; + + auto res = tulip::hook::writeMemory((void*)(base::get() + 0x69a0), patchBytes.data(), 6); + if (!res) + return; + + int exitCode = geodeEntry(nullptr); + if (exitCode != 0) + return; + + return reinterpret_cast<void(*)(void*, SEL, NSNotification*)>(geode::base::get() + 0x69a0)(self, sel, notification); +} + + +bool loadGeode() { + auto detourAddr = reinterpret_cast<uintptr_t>(&applicationDidFinishLaunchingHook) - geode::base::get() - 0x69a5; + auto detourAddrPtr = reinterpret_cast<uint8_t*>(&detourAddr); + + std::array<uint8_t, 5> patchBytes = { + 0xe9, detourAddrPtr[0], detourAddrPtr[1], detourAddrPtr[2], detourAddrPtr[3] + }; + + auto res = tulip::hook::writeMemory((void*)(base::get() + 0x69a0), patchBytes.data(), 5); + if (!res) + return false; + + return true; +} + +__attribute__((constructor)) void _entry() { + if (!loadGeode()) + return; +} + +#endif \ No newline at end of file