From b129f0a5032325f8fea0d49742509b9c8136fe83 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Sat, 18 May 2024 18:58:39 -0400 Subject: [PATCH] Attack Of The Templates! --- dependencies/symbol-processor/src | 2 +- launcher/src/crash-report.c | 1 + libreborn/include/libreborn/patch.h | 149 +++++++++++++++++++--------- libreborn/src/patch/patch.cpp | 6 +- mods/include/mods/misc/misc.h | 60 ++++++++--- mods/src/bucket/bucket.cpp | 4 +- mods/src/cake/cake.cpp | 2 +- mods/src/misc/api.cpp | 118 ---------------------- mods/src/misc/misc.cpp | 10 +- 9 files changed, 159 insertions(+), 193 deletions(-) diff --git a/dependencies/symbol-processor/src b/dependencies/symbol-processor/src index fbb9b6d6..eb49f25f 160000 --- a/dependencies/symbol-processor/src +++ b/dependencies/symbol-processor/src @@ -1 +1 @@ -Subproject commit fbb9b6d6da1a9dfa9290d420d1b2c34f91026111 +Subproject commit eb49f25fa45842ebff448cbadd347c883e66efb6 diff --git a/launcher/src/crash-report.c b/launcher/src/crash-report.c index ccc38024..6608d187 100644 --- a/launcher/src/crash-report.c +++ b/launcher/src/crash-report.c @@ -241,6 +241,7 @@ void setup_crash_report() { // Close Log File reborn_close_log(); + unsetenv(MCPI_LOG_ENV); // Show Crash Log #ifndef MCPI_HEADLESS_MODE diff --git a/libreborn/include/libreborn/patch.h b/libreborn/include/libreborn/patch.h index cb587b07..c7cb52d3 100644 --- a/libreborn/include/libreborn/patch.h +++ b/libreborn/include/libreborn/patch.h @@ -1,8 +1,6 @@ #pragma once #ifdef __cplusplus -extern "C" { -#endif // Patching Functions @@ -12,74 +10,127 @@ void reborn_init_patch(); // Replace Call Located At start With A Call To target void _overwrite_call(const char *file, int line, void *start, void *target); -#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target) +#define overwrite_call(...) \ + _overwrite_call(__FILE__, __LINE__, __VA_ARGS__) -#define _setup_fancy_overwrite(start, name, target) \ - static name##_t _original_for_##target = start; \ - static name##_t _helper_for_##target = __overwrite_helper_for_##name(target, _original_for_##target) +// Make Sure Function Is Only Called Once +template +static void _only_call_once() { + static bool _has_run = false; + if (_has_run) { + IMPOSSIBLE(); + } + _has_run = true; +} // Replace All Calls To Method start With target -void *_overwrite_calls(const char *file, int line, void *start, void *target); -#define overwrite_calls_manual(start, target) _overwrite_calls(__FILE__, __LINE__, start, target) -#define overwrite_calls(start, target) \ - { \ - _setup_fancy_overwrite(start, start, target); \ - start = (start##_t) overwrite_calls_manual((void *) start, (void *) _helper_for_##target); \ - } +void *_overwrite_calls_manual(const char *file, int line, void *start, void *target); +#define overwrite_calls_manual(...) \ + _overwrite_calls_manual(__FILE__, __LINE__, __VA_ARGS__) +template +static void _overwrite_calls(const char *file, int line, start_t (*create_helper)(overwrite_t, start_t), start_t &start, overwrite_t target) { + _only_call_once(); + start_t helper = create_helper(target, start); + start = (start_t) _overwrite_calls_manual(file, line, (void *) start, (void *) helper); +} +#define overwrite_calls(start, ...) \ + _overwrite_calls< \ + __COUNTER__, \ + start##_t, \ + __overwrite_##start##_t \ + >( \ + __FILE__, __LINE__, \ + __create_overwrite_helper_for_##start, \ + start, \ + __VA_ARGS__ \ + ) // Replace All Calls To Virtual Method start With target -#define _check_if_method_is_new(name) \ - { \ - if (!__is_new_method_##name()) { \ - ERR("Method Is Not \"New\""); \ - } \ - } -#define overwrite_virtual_calls(start, target) \ - { \ - _check_if_method_is_new(start); \ - _setup_fancy_overwrite(*start##_vtable_addr, start, target); \ - overwrite_calls_manual((void *) *start##_vtable_addr, (void *) _helper_for_##target); \ +template +static void _overwrite_virtual_calls(const char *file, int line, start_t (*create_helper)(overwrite_t, start_t), bool (*is_overwritable)(), start_t start, overwrite_t target) { + _only_call_once(); + if (!is_overwritable()) { + ERR("Virtual Method Is Not Overwritable"); } + start_t helper = create_helper(target, start); + _overwrite_calls_manual(file, line, (void *) start, (void *) helper); +} +#define overwrite_virtual_calls(start, ...) \ + _overwrite_virtual_calls< \ + __COUNTER__, \ + start##_t, \ + __overwrite_##start##_t \ + >( \ + __FILE__, __LINE__, \ + __create_overwrite_helper_for_##start, \ + __is_overwritable_##start, \ + *start##_vtable_addr, \ + __VA_ARGS__ \ + ) // Replace All Calls To start With target Within [to, from) -void _overwrite_calls_within(const char *file, int line, void *from, void *to, void *start, void *target); -#define overwrite_calls_within_manual(from, to, start, target) _overwrite_calls_within(__FILE__, __LINE__, from, to, start, target) -#define overwrite_calls_within(from, to, start, target) \ - { \ - start##_t type_check = target; \ - overwrite_calls_within_manual(from, to, (void *) start, (void *) type_check); \ - } +void _overwrite_calls_within_manual(const char *file, int line, void *from, void *to, void *start, void *target); +#define overwrite_calls_within_manual(...) \ + _overwrite_calls_within(__FILE__, __LINE__, __VA_ARGS__) +template +void _overwrite_calls_within(const char *file, int line, void *from, void *to, start_t start, start_t target) { + _overwrite_calls_within_manual(file, line, from, to, (void *) start, (void *) target); +} +#define overwrite_calls_within(from, to, start, ...) \ + _overwrite_calls_within< \ + start##_t \ + >( \ + __FILE__, __LINE__, \ + from, to, \ + start, \ + __VA_ARGS__ \ + ) // Get Target Address From BL Instruction void *extract_from_bl_instruction(unsigned char *from); // Replace Method start With target -void _overwrite(const char *file, int line, void *start, void *target); -#define overwrite_manual(start, target) _overwrite(__FILE__, __LINE__, (void *) start, (void *) target) -#define overwrite(start, target) \ - { \ - start##_t type_check = target; \ - overwrite_manual((void *) start, (void *) type_check); \ - } +void _overwrite_manual(const char *file, int line, void *start, void *target); +#define overwrite_manual(...) \ + _overwrite(__FILE__, __LINE__, __VA_ARGS__) +template +void _overwrite(const char *file, int line, start_t start, start_t target) { + _overwrite_manual(file, line, (void *) start, (void *) target); +} +#define overwrite(start, ...) \ + _overwrite< \ + start##_t \ + >( \ + __FILE__, __LINE__, \ + start, \ + __VA_ARGS__ \ + ) // Patch Instruction void _patch(const char *file, int line, void *start, unsigned char patch[4]); -#define patch(start, patch) _patch(__FILE__, __LINE__, start, patch) +#define patch(...) \ + _patch(__FILE__, __LINE__, __VA_ARGS__) // Patch 4 Bytes Of Data void _patch_address(const char *file, int line, void *start, void *target); -#define patch_address(start, target) _patch_address(__FILE__, __LINE__, (void *) start, (void *) target) +#define patch_address(...) \ + _patch_address(__FILE__, __LINE__, __VA_ARGS__) // Patch VTable Entry // This does not affect sub-classes. -#define patch_vtable(start, target) \ - { \ - start##_t type_check = target; \ - patch_address(start##_vtable_addr, (void *) type_check); \ - } - -#endif - -#ifdef __cplusplus +template +void _patch_vtable(const char *file, int line, start_t *start, start_t target) { + _patch_address(file, line, (void *) start, (void *) target); } +#define patch_vtable(start, ...) \ + _patch_vtable< \ + start##_t \ + >( \ + __FILE__, __LINE__, \ + start##_vtable_addr, \ + __VA_ARGS__ \ + ) + +#endif + #endif diff --git a/libreborn/src/patch/patch.cpp b/libreborn/src/patch/patch.cpp index 831b3d02..8026f8ed 100644 --- a/libreborn/src/patch/patch.cpp +++ b/libreborn/src/patch/patch.cpp @@ -77,7 +77,7 @@ static int _overwrite_calls_within_internal(const char *file, int line, void *fr #define TEXT_END 0x1020c0 // Overwrite All B(L) Intrusctions That Target The Specified Address #define NO_CALLSITE_ERROR "(%s:%i) Unable To Find Callsites For %p" -void *_overwrite_calls(const char *file, int line, void *start, void *target) { +void *_overwrite_calls_manual(const char *file, int line, void *start, void *target) { // Add New Target To Code Block void *code_block = update_code_block(target); @@ -97,7 +97,7 @@ void *_overwrite_calls(const char *file, int line, void *start, void *target) { // Return return code_block; } -void _overwrite_calls_within(const char *file, int line, void *from /* inclusive */, void *to /* exclusive */, void *target, void *replacement) { +void _overwrite_calls_within_manual(const char *file, int line, void *from /* inclusive */, void *to /* exclusive */, void *target, void *replacement) { // Add New Target To Code Block void *code_block = update_code_block(replacement); @@ -113,7 +113,7 @@ void _overwrite_calls_within(const char *file, int line, void *from /* inclusive } // Overwrite Function -void _overwrite(const char *file, int line, void *start, void *target) { +void _overwrite_manual(const char *file, int line, void *start, void *target) { // Replace the function's start with a call // to the replacement function. _overwrite_call_internal(file, line, start, target, 1); diff --git a/mods/include/mods/misc/misc.h b/mods/include/mods/misc/misc.h index 6bdcea18..9f0609bc 100644 --- a/mods/include/mods/misc/misc.h +++ b/mods/include/mods/misc/misc.h @@ -8,21 +8,53 @@ extern "C" { int32_t misc_get_real_selected_slot(Player *player); void misc_render_background(int color, Minecraft *minecraft, int x, int y, int width, int height); -typedef void (*misc_update_function_Minecraft_t)(Minecraft *obj); -void misc_run_on_update(misc_update_function_Minecraft_t function); // obj == Minecraft * -void misc_run_on_tick(misc_update_function_Minecraft_t function); // obj == Minecraft * -typedef void (*misc_update_function_Recipes_t)(Recipes *obj); -void misc_run_on_recipes_setup(misc_update_function_Recipes_t function); // obj == Recipes * -typedef void (*misc_update_function_FurnaceRecipes_t)(FurnaceRecipes *obj); -void misc_run_on_furnace_recipes_setup(misc_update_function_FurnaceRecipes_t function); // obj == FurnaceRecipes * typedef void (*misc_update_function_FillingContainer_t)(FillingContainer *obj); void misc_run_on_creative_inventory_setup(misc_update_function_FillingContainer_t function); // obj == FillingContainer * -typedef void (*misc_update_function_void_t)(void *obj); -void misc_run_on_tiles_setup(misc_update_function_void_t function); // obj == NULL -void misc_run_on_items_setup(misc_update_function_void_t function); // obj == NULL -void misc_run_on_language_setup(misc_update_function_void_t function); // obj == NULL -typedef bool (*misc_update_function_key_press_t)(Minecraft *minecrtaft, int key); -void misc_run_on_game_key_press(misc_update_function_key_press_t function); // In-Game Key Presses Only extern bool is_in_chat; -} \ No newline at end of file +} + +#define misc_run_on_update(...) \ + overwrite_virtual_calls(Minecraft_update, [](Minecraft_update_t _original, Minecraft *_self) { \ + _original(_self); \ + (__VA_ARGS__)(_self); \ + }) +#define misc_run_on_tick(...) \ + overwrite_calls(Minecraft_tick, [](Minecraft_tick_t _original, Minecraft *_self, int _tick, int _max_ticks) { \ + _original(_self, _tick, _max_ticks); \ + (__VA_ARGS__)(_self); \ + }) +#define misc_run_on_recipes_setup(...) \ + overwrite_calls(Recipes_constructor, [](Recipes_constructor_t _original, Recipes *_self) { \ + _original(_self); \ + (__VA_ARGS__)(_self); \ + return _self; \ + }) +#define misc_run_on_furnace_recipes_setup(...) \ + overwrite_calls(FurnaceRecipes_constructor, [](FurnaceRecipes_constructor_t _original, FurnaceRecipes *_self) { \ + _original(_self); \ + (__VA_ARGS__)(_self); \ + return _self; \ + }) +#define misc_run_on_tiles_setup(...) \ + overwrite_calls(Tile_initTiles, [](Tile_initTiles_t _original) { \ + (__VA_ARGS__)(); \ + _original(); \ + }) +#define misc_run_on_items_setup(...) \ + overwrite_calls(Item_initItems, [](Item_initItems_t _original) { \ + _original(); \ + (__VA_ARGS__)(); \ + }) +#define misc_run_on_language_setup(...) \ + overwrite_calls(I18n_loadLanguage, [](I18n_loadLanguage_t _original, AppPlatform *_self, std::string _language_name) { \ + _original(_self, _language_name); \ + (__VA_ARGS__)(); \ + }) +#define misc_run_on_game_key_press(...) \ + overwrite_calls(Gui_handleKeyPressed, [](Gui_handleKeyPressed_t _original, Gui *_self, int _key) { \ + if ((__VA_ARGS__)(_self->minecraft, _key)) { \ + return; \ + } \ + _original(_self, _key); \ + }) diff --git a/mods/src/bucket/bucket.cpp b/mods/src/bucket/bucket.cpp index f7f77039..50e04f51 100644 --- a/mods/src/bucket/bucket.cpp +++ b/mods/src/bucket/bucket.cpp @@ -207,7 +207,7 @@ static FoodItem *create_bucket(int32_t id, int32_t texture_x, int32_t texture_y, // Return return item; } -static void Item_initItems_injection(__attribute__((unused)) void *null) { +static void Item_initItems_injection() { bucket = create_bucket(69, 10, 4, "bucket"); } @@ -340,7 +340,7 @@ static void FurnaceTileEntity_tick_ItemInstance_setNull_injection(ItemInstance * } // Add the bucket name to the language file -static void Language_injection(__attribute__((unused)) void *null) { +static void Language_injection() { I18n::_strings.insert(std::make_pair("item.bucketMilk.name", "Milk Bucket")); } diff --git a/mods/src/cake/cake.cpp b/mods/src/cake/cake.cpp index 81111287..996a1fc0 100644 --- a/mods/src/cake/cake.cpp +++ b/mods/src/cake/cake.cpp @@ -153,7 +153,7 @@ static void make_cake() { cake->setDescriptionId(&name); } -static void Tile_initTiles_injection(__attribute__((unused)) void *null) { +static void Tile_initTiles_injection() { make_cake(); } diff --git a/mods/src/misc/api.cpp b/mods/src/misc/api.cpp index 054ff385..d9bdbfbb 100644 --- a/mods/src/misc/api.cpp +++ b/mods/src/misc/api.cpp @@ -27,56 +27,6 @@ } \ } -// Run Functions On Update -SETUP_CALLBACK(update, Minecraft); -// Handle Custom Update Behavior -static void Minecraft_update_injection(Minecraft_update_t original, Minecraft *minecraft) { - // Call Original Method - original(minecraft); - - // Run Functions - handle_misc_update(minecraft); -} - -// Run Functions On Tick -SETUP_CALLBACK(tick, Minecraft); -// Handle Custom Tick Behavior -static void Minecraft_tick_injection(Minecraft_tick_t original, Minecraft *minecraft, int32_t param_1, int32_t param_2) { - // Call Original Method - original(minecraft, param_1, param_2); - - // Run Functions - handle_misc_tick(minecraft); -} - -// Run Functions On Recipes Setup -SETUP_CALLBACK(recipes_setup, Recipes); -// Handle Custom Recipes Setup Behavior -static Recipes *Recipes_injection(Recipes_constructor_t original, Recipes *recipes) { - // Call Original Method - original(recipes); - - // Run Functions - handle_misc_recipes_setup(recipes); - - // Return - return recipes; -} - -// Run Functions On Furnace Recipes Setup -SETUP_CALLBACK(furnace_recipes_setup, FurnaceRecipes); -// Handle Custom Furnace Recipes Setup Behavior -static FurnaceRecipes *FurnaceRecipes_injection(FurnaceRecipes_constructor_t original, FurnaceRecipes *recipes) { - // Call Original Method - original(recipes); - - // Run Functions - handle_misc_furnace_recipes_setup(recipes); - - // Return - return recipes; -} - // Run Functions On Creative Inventory Setup SETUP_CALLBACK(creative_inventory_setup, FillingContainer); // Handle Custom Creative Inventory Setup Behavior @@ -88,60 +38,6 @@ static void Inventory_setupDefault_FillingContainer_addItem_call_injection(Filli handle_misc_creative_inventory_setup(filling_container); } -// Run Functions On Tiles Setup -SETUP_CALLBACK(tiles_setup, void); -// Handle Custom Tiles Setup Behavior -static void Tile_initTiles_injection(Tile_initTiles_t original) { - // Run Functions - handle_misc_tiles_setup(nullptr); - - // Call Original Method - original(); -} - -// Run Functions On Items Setup -SETUP_CALLBACK(items_setup, void); -// Handle Custom Items Setup Behavior -static void Item_initItems_injection(Item_initItems_t original) { - // Call Original Method - original(); - - // Run Functions - handle_misc_items_setup(nullptr); -} - -// Run Functions On Language Setup -SETUP_CALLBACK(language_setup, void); -// Handle Custom Items Setup Behavior -static void I18n_loadLanguage_injection(I18n_loadLanguage_t original, AppPlatform *app, std::string language_name) { - // Call Original Method - original(app, std::move(language_name)); - - // Run Functions - handle_misc_language_setup(nullptr); -} - -// Run Functions On GUI Key Press -STORE_CALLBACK(game_key_press, key_press) -static bool handle_misc_game_key_press(Minecraft *minecraft, int key) { - for (misc_update_function_key_press_t function : get_misc_game_key_press_functions()) { - if (function(minecraft, key)) { - return true; - } - } - return false; -} -// Handle Key Presses -static void Gui_handleKeyPressed_injection(Gui_handleKeyPressed_t original, Gui *self, int key) { - // Run Functions - if (handle_misc_game_key_press(self->minecraft, key)) { - return; - } - - // Call Original Method - original(self, key); -} - // Render Fancy Background void misc_render_background(int color, Minecraft *minecraft, int x, int y, int width, int height) { // https://github.com/ReMinecraftPE/mcpe/blob/f0d65eaecec1b3fe9c2f2b251e114a890c54ab77/source/client/gui/components/RolledSelectionList.cpp#L169-L179 @@ -166,20 +62,6 @@ void misc_render_background(int color, Minecraft *minecraft, int x, int y, int w // Init void _init_misc_api() { - // Handle Custom Update Behavior - overwrite_virtual_calls(Minecraft_update, Minecraft_update_injection); - // Handle Custom Tick Behavior - overwrite_calls(Minecraft_tick, Minecraft_tick_injection); - // Handle Custom Recipe Setup Behavior - overwrite_calls(Recipes_constructor, Recipes_injection); - overwrite_calls(FurnaceRecipes_constructor, FurnaceRecipes_injection); // Handle Custom Creative Inventory Setup Behavior overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection); - // Handle Custom Item/Tile Init Behavior - overwrite_calls(Tile_initTiles, Tile_initTiles_injection); - overwrite_calls(Item_initItems, Item_initItems_injection); - // Handle Custom Language Entries - overwrite_calls(I18n_loadLanguage, I18n_loadLanguage_injection); - // Handle Key Presses - overwrite_calls(Gui_handleKeyPressed, Gui_handleKeyPressed_injection); } diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 48d65a2b..eed8b845 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -822,10 +822,10 @@ void init_misc() { #ifdef MCPI_HEADLESS_MODE // Don't Render Game In Headless Mode - overwrite_manual(GameRenderer_render, nop); - overwrite_manual(NinecraftApp_initGLStates, nop); - overwrite_manual(Gui_onConfigChanged, nop); - overwrite_manual(LevelRenderer_generateSky, nop); + overwrite_manual((void *) GameRenderer_render, (void *) nop); + overwrite_manual((void *) NinecraftApp_initGLStates, (void *) nop); + overwrite_manual((void *) Gui_onConfigChanged, (void *) nop); + overwrite_manual((void *) LevelRenderer_generateSky, (void *) nop); #else // Improved Cursor Rendering if (feature_has("Improved Cursor Rendering", server_disabled)) { @@ -849,7 +849,7 @@ void init_misc() { // Remove Forced GUI Lag if (feature_has("Remove Forced GUI Lag (Can Break Joining Servers)", server_enabled)) { - overwrite_manual(Common_sleepMs, nop); + overwrite_manual((void *) Common_sleepMs, (void *) nop); } #ifndef MCPI_HEADLESS_MODE