diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 9cc21420..6da53abe 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -12,6 +12,14 @@ body: - "Windows" validations: required: true + - type: input + id: commit + attributes: + label: SDK commit + description: The commit you used to compile your code with. If the bug is not related with your mod, you can leave this field empty. + placeholder: "Example: a674b97" + validations: + required: false - type: input id: version attributes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 92540ae4..a5798580 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,12 @@ include(cmake/GeodeFile.cmake) include(cmake/Platform.cmake) include(cmake/CPM.cmake) +# this is needed for cross compilation on linux, +# since fmtlib will fail to compile otherwise +if (GEODE_DISABLE_FMT_CONSTEVAL) + target_compile_definitions(${PROJECT_NAME} INTERFACE -DFMT_CONSTEVAL=) +endif() + CPMAddPackage("gh:geode-sdk/json#2b76460") CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:gulrak/filesystem#3e5b930") @@ -77,8 +83,11 @@ set(GEODE_CODEGEN_BINARY_OUT ${CMAKE_CURRENT_BINARY_DIR}/codegen) ExternalProject_Add(CodegenProject BUILD_ALWAYS ON SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/codegen - CMAKE_CACHE_ARGS "-DCMAKE_INSTALL_PREFIX:STRING=${GEODE_CODEGEN_BINARY_OUT}" - CMAKE_ARGS ${GEODE_CODEGEN_CMAKE_ARGS} + # manually set configure command as to not inherit generator used by geode, + # this should hopefully fix generator cache mismatch between different projects, however + # it causes a warning to be shown every time. if you know a better solution please tell us ok thx + CONFIGURE_COMMAND ${CMAKE_COMMAND} ${GEODE_CODEGEN_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:STRING=${GEODE_CODEGEN_BINARY_OUT} -S -B + INSTALL_COMMAND ${CMAKE_COMMAND} --install --config $ ) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index d366c386..91741b45 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -186,15 +186,13 @@ class ButtonSprite : cocos2d::CCSprite { ) = win 0x134b0, mac 0x4f1d0; [[docs(" - /** - * Create a ButtonSprite with a top sprite and a texture. - * @param topSprite The top sprite to add on top of the sprite - * @param width Sprite width; ignored if `absolute` is false - * @param absolute Whether to use absolute width or not - * @param texture The name of the background sprite file (can't be in a spritesheet) - * @param height The height of the button, leave 0 for automatic - * @param scale Scale of top sprite - */ + Create a ButtonSprite with a top sprite and a texture. + @param topSprite The top sprite to add on top of the sprite + @param width Sprite width; ignored if `absolute` is false + @param absolute Whether to use absolute width or not + @param texture The name of the background sprite file (can't be in a spritesheet) + @param height The height of the button, leave 0 for automatic + @param scale Scale of top sprite ")]] static ButtonSprite* create( cocos2d::CCSprite* topSprite, @@ -208,26 +206,27 @@ class ButtonSprite : cocos2d::CCSprite { } [[docs(" - /** - * Create a ButtonSprite with text, a font and a texture. - * @param caption The text of the ButtonSprite - * @param width Sprite width; ignored if `absolute` is false - * @param absolute Whether to use absolute width or not - * @param font The name of the BM font file to use - * @param texture The name of the background sprite file (can't be in a spritesheet) - * @param height The height of the button, leave 0 for automatic - * @param scale Scale of text - * @returns Pointer to the created ButtonSprite, or nullptr on error - */ + Create a ButtonSprite with text, a font and a texture. + @param caption The text of the ButtonSprite + @param width Sprite width; ignored if `absolute` is false + @param absolute Whether to use absolute width or not + @param font The name of the BM font file to use + @param texture The name of the background sprite file (can't be in a spritesheet) + @param height The height of the button, leave 0 for automatic + @param scale Scale of text + @returns Pointer to the created ButtonSprite, or nullptr on error ")]] static ButtonSprite* create(const char* caption, int width, bool absolute, const char* font, const char* texture, float height, float scale) { return create(caption, width, 0, scale, absolute, font, texture, height); } - inline static ButtonSprite* create(char const* caption) { + static ButtonSprite* create(char const* caption) { return ButtonSprite::create(caption, 0, 0, "goldFont.fnt", "GJ_button_01.png", .0f, 1.f); } - inline static ButtonSprite* create(char const* caption, const char* font, const char* texture, float scale = 1.f) { + static ButtonSprite* create(char const* caption, const char* font, const char* texture) { + return ButtonSprite::create(caption, 0, 0, font, texture, .0f, 1.f); + } + static ButtonSprite* create(char const* caption, const char* font, const char* texture, float scale) { return ButtonSprite::create(caption, 0, 0, font, texture, .0f, scale); } static ButtonSprite* create(char const*, int, int, float, bool) = mac 0x4fa40; @@ -1235,6 +1234,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ void editObject2(cocos2d::CCObject* sender) = win 0x8d1b0; void editGroup(cocos2d::CCObject* sender) = win 0x8d720; void moveObjectCall(cocos2d::CCObject* sender) = mac 0x29830, win 0x8db30; + void moveObjectCall(EditCommand) = win 0x8db50; void transformObjectCall(cocos2d::CCObject* sender) = mac 0x29860, win 0x8def0; void onDelete(cocos2d::CCObject* sender) = mac 0x1b3d0, win 0x7b8d0; void onDeleteSelected(cocos2d::CCObject* sender) = mac 0xb990, win 0x7bf50; @@ -1268,6 +1268,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ void onUngroupSticky(cocos2d::CCObject* sender) = mac 0xc1d0, win 0x87ac0; void onGoToLayer(cocos2d::CCObject* sender) = win 0x886b0; void onGoToBaseLayer(cocos2d::CCObject* sender) = win 0x88790; + void onToggleGuide(cocos2d::CCObject* sender) = mac 0x19da0, win 0x79160; void editColor(cocos2d::CCObject* sender) = mac 0x19190, win 0x8d3c0; void alignObjects(cocos2d::CCArray* objs, bool alignY) = mac 0x2cea0, win 0x8f320; virtual void scrollWheel(float vertical, float horizontal) = win 0x921d0, mac 0x31370, ios 0x2c4884; @@ -2590,7 +2591,7 @@ class GooglePlayDelegate { class GooglePlayManager : cocos2d::CCNode { virtual bool init() = win 0x11070; - static GooglePlayManager *sharedState() = win 0x4295a0; + static GooglePlayManager* sharedState() = win 0x295a0; } class GameLevelManager : cocos2d::CCNode { @@ -3763,7 +3764,7 @@ class LevelPage { class LevelSearchLayer : cocos2d::CCLayer { static LevelSearchLayer* create() = win 0x17d9c0; - bool init() = mac 0x384770, win 0x17da60; + virtual bool init() = mac 0x384770, win 0x17da60; GJSearchObject* getSearchObject(SearchType, gd::string) = mac 0x388a50, win 0x1805f0; void onMoreOptions(cocos2d::CCObject*) = win 0x17f500; void onSearch(cocos2d::CCObject*) = win 0x180fc0; @@ -3931,7 +3932,7 @@ class MapPackCell : TableViewCell { class MenuGameLayer { void resetPlayer() = mac 0x28fdc0, win 0x18f4b0; void destroyPlayer() = win 0x190100; - void update(float) = mac 0x28fa70, win 0x18f190; + virtual void update(float) = mac 0x28fa70, win 0x18f190; virtual bool init() = win 0x18e770; void updateColors() = win 0x18edd0; } @@ -3972,12 +3973,12 @@ class MessageListDelegate {} class MoreSearchLayer : FLAlertLayer { static MoreSearchLayer* create() = win 0x182520; - bool init() = win 0x1825c0; + virtual bool init() = win 0x1825c0; } class MoreOptionsLayer { static MoreOptionsLayer* create() = win 0x1de850; - bool init() = mac 0x43f470, win 0x1DE8F0; + virtual bool init() = mac 0x43f470, win 0x1DE8F0; void addToggle(const char* name, const char* key, const char* info) = mac 0x440430, win 0x1df6b0; void onKeybindings(cocos2d::CCObject* sender) = win 0x749d0; void onToggle(cocos2d::CCObject* sender) = mac 0x441370; @@ -4127,7 +4128,7 @@ class PauseLayer : CCBlockLayer { virtual void customSetup() = mac 0x20b300, win 0x1e4620; void onRestart(cocos2d::CCObject* sender) = win 0x1e6040; - void keyDown(cocos2d::enumKeyCodes) = mac 0x20cc80, win 0x1E6580; + virtual void keyDown(cocos2d::enumKeyCodes) = mac 0x20cc80, win 0x1E6580; bool m_unknown; bool m_unknown2; diff --git a/codegen/CMakeLists.txt b/codegen/CMakeLists.txt index f0257203..960f382c 100644 --- a/codegen/CMakeLists.txt +++ b/codegen/CMakeLists.txt @@ -4,7 +4,7 @@ project(Codegen LANGUAGES C CXX) include(../cmake/CPM.cmake) CPMAddPackage("gh:fmtlib/fmt#9.1.0") -CPMAddPackage("gh:camila314/Broma#1.0.0") +CPMAddPackage("gh:geode-sdk/Broma#eb45fab") file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp @@ -22,4 +22,4 @@ target_precompile_headers(Codegen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/Shared.hpp ) -install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) \ No newline at end of file +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index 8ae7f092..c87fb974 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -40,13 +40,18 @@ public: char const* monostate_constructor_cutoff = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base}) )GEN"; - char const* function_definition = R"GEN({docs} {static}{virtual}{return_type} {function_name}({parameters}){const}; + char const* function_definition = R"GEN( + /** +{docs}{docs_addresses} */ + {static}{virtual}{return_type} {function_name}({parameters}){const}; )GEN"; char const* error_definition = R"GEN( #ifdef GEODE_WARN_INCORRECT_MEMBERS [[deprecated("Function is not implemented - will throw at runtime!!!")]] #endif + /** +{docs}{docs_addresses} */ {static}{return_type} {function_name}({parameters}){const}{{ throw std::runtime_error("Use of undefined function " + GEODE_PRETTY_FUNCTION); }} @@ -56,6 +61,8 @@ public: #ifdef GEODE_WARN_INCORRECT_MEMBERS [[deprecated("Use of undefined virtual function - will crash at runtime!!!")]] #endif + /** +{docs}{docs_addresses} */ {virtual}{return_type} {function_name}({parameters}){const}{{ #ifdef GEODE_NO_UNDEFINED_VIRTUALS static_assert(false, "Undefined virtual function - implement in GeometryDash.bro"); @@ -68,10 +75,13 @@ public: #ifdef GEODE_WARN_INCORRECT_MEMBERS [[deprecated("Member placed incorrectly - will crash at runtime!!!")]] #endif - )GEN"; +)GEN"; char const* structor_definition = R"GEN( - {function_name}({parameters});)GEN"; + /** +{docs}{docs_addresses} */ + {function_name}({parameters}); +)GEN"; // requires: type, member_name, array char const* member_definition = R"GEN( {type} {member_name}; @@ -84,6 +94,52 @@ public: )GEN"; }} +inline std::string nameForPlatform(Platform platform) { + switch (platform) { + case Platform::Mac: return "MacOS"; + case Platform::Windows: return "Windows"; + case Platform::iOS: return "iOS"; + case Platform::Android: return "Android"; + default: // unreachable + return "Windows"; + } +} + + +std::string generateAddressDocs(Field const& field, FunctionBindField* fn) { + std::string ret; + + for (auto platform : {Platform::Mac, Platform::Windows, Platform::iOS, Platform::Android}) { + auto status = codegen::getStatusWithPlatform(platform, field); + + if (status == BindStatus::NeedsBinding) { + ret += fmt::format(" * @note[short] {}: 0x{:x}\n", + nameForPlatform(platform), + codegen::platformNumberWithPlatform(platform, fn->binds) + ); + } + else if (status == BindStatus::Binded) { + ret += fmt::format(" * @note[short] {}\n", + nameForPlatform(platform) + ); + } + + } + + return ret; +} + +std::string generateDocs(std::string const& docs) { + if (docs.size() < 7) return ""; + auto ret = docs.substr(1, docs.size() - 6); // i hate this but idk how to generalize + + for (auto next = ret.find(" "); next != std::string::npos; next = ret.find(" ")) { + ret.replace(next, 8, " * "); + } + + return ret; +} + std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singleFolder) { std::string output; @@ -137,6 +193,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl FunctionBegin* fb; char const* used_format = format_strings::function_definition; + std::string addressDocs; + if (auto i = field.get_as()) { single_output += "\t" + i->inner + "\n"; continue; @@ -158,6 +216,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl continue; } else if (auto fn = field.get_as()) { fb = &fn->beginning; + addressDocs = " * @note[short] Out of line\n"; + } else if (auto fn = field.get_as()) { fb = &fn->beginning; @@ -170,8 +230,12 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl if (fb->type != FunctionType::Normal) continue; } + + addressDocs = generateAddressDocs(field, fn); } + std::string docs = generateDocs(fb->docs); + single_output += fmt::format(used_format, fmt::arg("virtual", str_if("virtual ", fb->is_virtual)), fmt::arg("static", str_if("static ", fb->is_static)), @@ -181,7 +245,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl fmt::arg("index", field.field_id), fmt::arg("parameters", codegen::getParameters(*fb)), fmt::arg("return_type", fb->ret.name), - fmt::arg("docs", fb->docs) + fmt::arg("docs_addresses", addressDocs), + fmt::arg("docs", docs) ); } diff --git a/codegen/src/Main.cpp b/codegen/src/Main.cpp index 5a504b37..53d2f941 100644 --- a/codegen/src/Main.cpp +++ b/codegen/src/Main.cpp @@ -34,7 +34,7 @@ int main(int argc, char** argv) try { writeFile(writeDir / "GeneratedAddress.cpp", generateAddressHeader(root)); writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root, writeDir / "modify")); // writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root)); - writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root)); + // writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root)); writeFile(writeDir / "GeneratedBinding.hpp", generateBindingHeader(root, writeDir / "binding")); writeFile(writeDir / "GeneratedPredeclare.hpp", generatePredeclareHeader(root)); writeFile(writeDir / "GeneratedSource.cpp", generateBindingSource(root)); diff --git a/codegen/src/Shared.hpp b/codegen/src/Shared.hpp index 1ae45ceb..c93f398e 100644 --- a/codegen/src/Shared.hpp +++ b/codegen/src/Shared.hpp @@ -70,22 +70,26 @@ namespace codegen { inline Platform platform; - inline uintptr_t platformNumber(PlatformNumber const& p) { - switch (codegen::platform) { - case Platform::Mac: return p.mac; - case Platform::Windows: return p.win; - case Platform::iOS: return p.ios; - case Platform::Android: return p.android; + inline uintptr_t platformNumberWithPlatform(Platform p, PlatformNumber const& pn) { + switch (p) { + case Platform::Mac: return pn.mac; + case Platform::Windows: return pn.win; + case Platform::iOS: return pn.ios; + case Platform::Android: return pn.android; default: // unreachable - return p.win; + return pn.win; } } - inline BindStatus getStatus(Field const& field) { + inline uintptr_t platformNumber(PlatformNumber const& p) { + return platformNumberWithPlatform(codegen::platform, p); + } + + inline BindStatus getStatusWithPlatform(Platform p, Field const& field) { FunctionBegin const* fb; if (auto fn = field.get_as()) { - if (platformNumber(fn->binds)) return BindStatus::NeedsBinding; + if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding; fb = &fn->beginning; } @@ -96,7 +100,7 @@ namespace codegen { // if (field.parent.rfind("GDString", 0) == 0) return BindStatus::NeedsBinding; - if (platform == Platform::Android) { + if (p == Platform::Android) { for (auto& [type, name] : fb->args) { if (type.name.find("gd::") != std::string::npos) return BindStatus::NeedsBinding; } @@ -108,13 +112,17 @@ namespace codegen { if (fb->type == FunctionType::Normal) { if (field.parent.rfind("fmod::", 0) == 0) return BindStatus::Binded; - if (field.parent.rfind("cocos2d::", 0) == 0 && platform == Platform::Windows) + if (field.parent.rfind("cocos2d::", 0) == 0 && p == Platform::Windows) return BindStatus::Binded; } return BindStatus::Unbindable; } + inline BindStatus getStatus(Field const& field) { + return getStatusWithPlatform(codegen::platform, field); + } + inline std::string getParameters(FunctionBegin const& f) { // int p0, float p1 std::vector parameters; diff --git a/codegen/src/TypeGen.cpp b/codegen/src/TypeGen.cpp index f52143fc..e69de29b 100644 --- a/codegen/src/TypeGen.cpp +++ b/codegen/src/TypeGen.cpp @@ -1,96 +0,0 @@ -#include "Shared.hpp" -#include "TypeOpt.hpp" -#include - -std::string generateTypeHeader(Root& root) { - std::string output; - - TypeBank bank; - bank.loadFrom(root); - - std::map used_returns; - std::map used_funcs; - std::map used_pures; - - int i = 0; - for (auto& f : bank.typeList()) { - - char const* return_fmt = "using ret{index} = {return};"; - char const* func_fmt; - char const* pure_fmt = "ret{ret_index}({parameter_types});"; - char const* meta_fmt; - char const* member_fmt; - - switch (f.type) { - case FuncType::Member: - func_fmt = "ret{ret_index}(*)( {const}{class_name}*{parameter_type_comma}{parameter_types});"; - meta_fmt = "ret{ret_index}({const}{class_name}*{parameter_type_comma}{parameter_types});"; - member_fmt = "ret{ret_index}({class_name}::*)({parameter_types}){const};"; - break; - case FuncType::Static: - func_fmt = "ret{ret_index}(*)({parameter_types});"; - meta_fmt = "ret{ret_index}({parameter_types});"; - member_fmt = "func{index};"; - break; - case FuncType::Structor: - func_fmt = "ret{ret_index}(*)({class_name}*{parameter_type_comma}{parameter_types});"; - meta_fmt = "ret{ret_index}({const}{class_name}*{parameter_type_comma}{parameter_types});"; - member_fmt = "func{index};"; - break; - } - - if (used_returns.count(f.return_type) == 0) { - output += fmt::format(return_fmt, - fmt::arg("index", i), - fmt::arg("return", f.return_type) - ) + "\n"; - used_returns[f.return_type] = i; - } - int ret_index = used_returns[f.return_type]; - - std::string pure_val = fmt::format(pure_fmt, - fmt::arg("ret_index", ret_index), - fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")) - ); - if (used_pures.count(pure_val) == 0) { - output += fmt::format("using pure{} = {}\n", i, pure_val); - used_pures[pure_val] = i; - } - - std::string func_val = fmt::format(func_fmt, - fmt::arg("ret_index", ret_index), - fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")), - fmt::arg("parameter_type_comma", str_if(", ", !f.parameter_types.empty())), - fmt::arg("class_name", f.class_name), - fmt::arg("const", str_if(" const ", f.is_const)) - ); - std::string meta_val = fmt::format(meta_fmt, - fmt::arg("ret_index", ret_index), - fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")), - fmt::arg("parameter_type_comma", str_if(", ", !f.parameter_types.empty())), - fmt::arg("class_name", f.class_name), - fmt::arg("const", str_if(" const ", f.is_const)) - ); - std::string member_val = fmt::format(member_fmt, - fmt::arg("ret_index", ret_index), - fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")), - fmt::arg("class_name", f.class_name), - fmt::arg("const", str_if(" const ", f.is_const)), - fmt::arg("index", i) - ); - - if (used_funcs.count(func_val) == 0) { - output += fmt::format("using func{index} = {func}\nusing meta{index} = {meta}\nusing member{index} = {member}\n", - fmt::arg("index", i), - fmt::arg("func", func_val), - fmt::arg("meta", meta_val), - fmt::arg("member", member_val) - ); - used_funcs[func_val] = i; - } - - ++i; - } - - return output; -} diff --git a/loader/include/Geode/loader/Log.hpp b/loader/include/Geode/loader/Log.hpp index bea6cd1b..8681efaf 100644 --- a/loader/include/Geode/loader/Log.hpp +++ b/loader/include/Geode/loader/Log.hpp @@ -108,25 +108,19 @@ namespace geode { class GEODE_DLL Logger { private: - static inline std::vector s_logs; - static inline std::ofstream s_logStream; + static std::vector& logs(); + static std::ofstream& logStream(); Logger() = delete; ~Logger() = delete; // logs - static void _push(Log&& log); - public: static void setup(); - static inline void push(Log&& log) { - Logger::_push(std::move(log)); - } + static void push(Log&& log); - static inline void pop(Log* log) { - geode::utils::ranges::remove(Logger::s_logs, *log); - } + static void pop(Log* log); static std::vector list(); static void clear(); diff --git a/loader/include/Geode/loader/Setting.hpp b/loader/include/Geode/loader/Setting.hpp index 0c77f265..cb3134a8 100644 --- a/loader/include/Geode/loader/Setting.hpp +++ b/loader/include/Geode/loader/Setting.hpp @@ -219,9 +219,9 @@ namespace geode { using ColorAlphaSettingValue = GeodeSettingValue; template - struct SettingValueSetter { - static GEODE_DLL T get(SettingValue* setting); - static GEODE_DLL void set(SettingValue* setting, T const& value); + struct GEODE_DLL SettingValueSetter { + static T get(SettingValue* setting); + static void set(SettingValue* setting, T const& value); }; } diff --git a/loader/include/Geode/modify/Modify.hpp b/loader/include/Geode/modify/Modify.hpp index 3b046c96..e2ed7c85 100644 --- a/loader/include/Geode/modify/Modify.hpp +++ b/loader/include/Geode/modify/Modify.hpp @@ -106,7 +106,7 @@ namespace geode::modifier { class ModifyDerive { public: ModifyDerive() { - static_assert(alwaysFalse, "Custom Modify not implemented."); + static_assert(alwaysFalse, "Modified class not recognized, please include to be able to use it."); } }; } diff --git a/loader/include/Geode/utils/addresser.hpp b/loader/include/Geode/utils/addresser.hpp index d37e65a6..96de6db6 100644 --- a/loader/include/Geode/utils/addresser.hpp +++ b/loader/include/Geode/utils/addresser.hpp @@ -77,10 +77,10 @@ namespace geode::addresser { } // I gave up - template - static Class* generateInstance(Class*) { - return friendCreate(nullptr); - } + // template + // static Class* generateInstance(Class*) { + // return friendCreate(nullptr); + // } // I extra gave up static cocos2d::extension::CCScrollView* generateInstance(cocos2d::extension::CCScrollView*) { @@ -131,15 +131,7 @@ namespace geode::addresser { // [[this + thunk] + offset] is the f we want auto address = *(intptr_t*)(*(intptr_t*)(reference_cast(ins) + thunk) + index); -#ifdef GEODE_IS_WINDOWS - // check if first instruction is a jmp, i.e. if the func is a thunk - if (*reinterpret_cast(address) == 0x25ff) { - // read where the jmp points to and jump there - address = *reinterpret_cast(address + 2); - // that then contains the actual address of the func - address = *reinterpret_cast(address); - } -#endif + address = followThunkFunction(address); return address; } @@ -171,14 +163,16 @@ namespace geode::addresser { return addressOfNonVirtual(reinterpret_cast(func)); } + static intptr_t followThunkFunction(intptr_t address); + template static intptr_t addressOfNonVirtual(R (T::*func)(Ps...)) { - return geode::cast::reference_cast(func); + return followThunkFunction(geode::cast::reference_cast(func)); } template static intptr_t addressOfNonVirtual(R (*func)(Ps...)) { - return geode::cast::reference_cast(func); + return followThunkFunction(geode::cast::reference_cast(func)); } template diff --git a/loader/src/loader/Log.cpp b/loader/src/loader/Log.cpp index c9204b71..61f4f3cb 100644 --- a/loader/src/loader/Log.cpp +++ b/loader/src/loader/Log.cpp @@ -183,30 +183,43 @@ void Log::addFormat(std::string_view formatStr, std::span compo // Logger -void Logger::setup() { - s_logStream = std::ofstream(dirs::getGeodeLogDir() / log::generateLogName()); +std::vector& Logger::logs() { + static std::vector logs; + return logs; +} +std::ofstream& Logger::logStream() { + static std::ofstream logStream; + return logStream; } -void Logger::_push(Log&& log) { +void Logger::setup() { + logStream() = std::ofstream(dirs::getGeodeLogDir() / log::generateLogName()); +} + +void Logger::push(Log&& log) { std::string logStr = log.toString(true); LoaderImpl::get()->logConsoleMessage(logStr); - s_logStream << logStr << std::endl; + logStream() << logStr << std::endl; - s_logs.emplace_back(std::forward(log)); + logs().emplace_back(std::forward(log)); +} + +void Logger::pop(Log* log) { + geode::utils::ranges::remove(Logger::logs(), *log); } std::vector Logger::list() { - std::vector logs; - logs.reserve(s_logs.size()); - for (auto& log : s_logs) { - logs.push_back(&log); + std::vector logs_; + logs_.reserve(logs().size()); + for (auto& log : logs()) { + logs_.push_back(&log); } - return logs; + return logs_; } void Logger::clear() { - s_logs.clear(); + logs().clear(); } // Misc diff --git a/loader/src/loader/Setting.cpp b/loader/src/loader/Setting.cpp index 4b5d0b3e..c8754dff 100644 --- a/loader/src/loader/Setting.cpp +++ b/loader/src/loader/Setting.cpp @@ -275,18 +275,6 @@ std::string SettingValue::getKey() const { typename type_##Setting::ValueType const& value \ ) const -// instantiate value setters - -namespace geode { - template struct SettingValueSetter; - template struct SettingValueSetter; - template struct SettingValueSetter; - template struct SettingValueSetter; - template struct SettingValueSetter; - template struct SettingValueSetter; - template struct SettingValueSetter; -} - // instantiate values namespace geode { @@ -370,6 +358,18 @@ IMPL_NODE_AND_SETTERS(File); IMPL_NODE_AND_SETTERS(Color); IMPL_NODE_AND_SETTERS(ColorAlpha); +// instantiate value setters + +namespace geode { + template struct SettingValueSetter; + template struct SettingValueSetter; + template struct SettingValueSetter; + template struct SettingValueSetter; + template struct SettingValueSetter; + template struct SettingValueSetter; + template struct SettingValueSetter; +} + // SettingChangedEvent SettingChangedEvent::SettingChangedEvent(Mod* mod, SettingValue* value) diff --git a/loader/src/utils/addresser.cpp b/loader/src/utils/addresser.cpp index d9a4c9b8..9fd65c2f 100644 --- a/loader/src/utils/addresser.cpp +++ b/loader/src/utils/addresser.cpp @@ -65,3 +65,16 @@ namespace { Addresser::MultipleInheritance* Addresser::instance() { return reinterpret_cast(&TableTable::table); } + +intptr_t Addresser::followThunkFunction(intptr_t address) { +#ifdef GEODE_IS_WINDOWS + // check if first instruction is a jmp dword ptr [....], i.e. if the func is a thunk + if (*reinterpret_cast(address) == 0xFF && *reinterpret_cast(address + 1) == 0x25) { + // read where the jmp reads from + address = *reinterpret_cast(address + 2); + // that then contains the actual address of the func + address = *reinterpret_cast(address); + } +#endif + return address; +} \ No newline at end of file