From 99aac006f4935a2505220ad7a9e71973b3d08d75 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Fri, 20 Nov 2020 13:36:03 -0500 Subject: [PATCH] Add Animated Water --- MODDING.md | 30 ++++++++++ debian/client/common/usr/bin/minecraft-pi | 2 +- mods/include/libcore/libcore.h | 3 + mods/src/core.c | 16 +++++- mods/src/extra.cpp | 69 ++++++++++++++--------- 5 files changed, 91 insertions(+), 29 deletions(-) diff --git a/MODDING.md b/MODDING.md index 1da544c2d..0894b6368 100644 --- a/MODDING.md +++ b/MODDING.md @@ -37,6 +37,36 @@ __attribute__((constructor)) static void init() { } ``` +### ``void overwrite_call(void *start, void *original)`` +This allows you to overwrite a specific call of a function rather than the function itself. This allows you to call the original function. However, this does not effect VTables. + +#### Parameters +- **start:** The address of the function call to overwrite. +- **target:** The function call you are replacing it with. + +#### Return Value +None + +#### Warning +This method can only be safely used 512 times in total. + +#### Example +```c +typedef int (*func_t)(int a, int b); +static func_t func = (func_t) 0xabcde; +static void *func_original = NULL; + +static int func_injection(int a, int b) { + (*func)(a, b); + + return a + 4; +} + +__attribute__((constructor)) static void init() { + overwrite_call((void *) 0xabcd, func_injection); +} +``` + ### ``void overwrite_calls(void *start, void *original)`` This allows you to overwrite all calls of a function rather than the function itself. This allows you to call the original function. However, this does not effect VTables. diff --git a/debian/client/common/usr/bin/minecraft-pi b/debian/client/common/usr/bin/minecraft-pi index 31960dfb8..9b379520f 100755 --- a/debian/client/common/usr/bin/minecraft-pi +++ b/debian/client/common/usr/bin/minecraft-pi @@ -4,7 +4,7 @@ set -e # Ensure Features Are Selected if [ -z "${MCPI_SUBSHELL}" ]; then - MCPI_FEATURES="$(zenity --class 'Minecraft - Pi edition' --list --checklist --column 'Enabled' --column 'Feature' TRUE 'Touch GUI' FALSE 'Survival Mode' TRUE 'Fix Bow & Arrow' TRUE 'Fix Attacking' TRUE 'Mob Spawning' TRUE 'Fancy Graphics' TRUE 'Disable Autojump By Default' TRUE 'Fix Sign Placement' TRUE 'Show Block Outlines' FALSE 'Expand Creative Inventory' FALSE 'Peaceful Mode')" + MCPI_FEATURES="$(zenity --class 'Minecraft - Pi edition' --list --checklist --column 'Enabled' --column 'Feature' TRUE 'Touch GUI' FALSE 'Survival Mode' TRUE 'Fix Bow & Arrow' TRUE 'Fix Attacking' TRUE 'Mob Spawning' TRUE 'Fancy Graphics' TRUE 'Disable Autojump By Default' TRUE 'Fix Sign Placement' TRUE 'Show Block Outlines' FALSE 'Expand Creative Inventory' FALSE 'Peaceful Mode' TRUE 'Animated Water')" MCPI_USERNAME="$(zenity --class 'Minecraft - Pi edition' --entry --text 'Minecraft Username:' --entry-text 'StevePi')" fi export MCPI_FEATURES diff --git a/mods/include/libcore/libcore.h b/mods/include/libcore/libcore.h index 08c637a02..fc4acb286 100644 --- a/mods/include/libcore/libcore.h +++ b/mods/include/libcore/libcore.h @@ -29,6 +29,9 @@ extern "C" { \ __attribute__((__used__)) return_type name args +void _overwrite_call(const char *file, int line, void *start, void *target); +#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target); + void _overwrite_calls(const char *file, int line, void *start, void *target); #define overwrite_calls(start, target) _overwrite_calls(__FILE__, __LINE__, start, target); diff --git a/mods/src/core.c b/mods/src/core.c index 82d5ab682..46bf21e8a 100644 --- a/mods/src/core.c +++ b/mods/src/core.c @@ -101,8 +101,7 @@ static unsigned char *code_block = NULL; #define CODE_SIZE 8 static int code_block_remaining = CODE_BLOCK_SIZE; -// Overwrite Function Calls -void _overwrite_calls(const char *file, int line, void *start, void *target) { +static void update_code_block(void *target) { // BL Instructions Can Only Access A Limited Portion of Memory, So This Allocates Memory Closer To The Original Instruction, That When Run, Will Jump Into The Actual Target if (code_block == NULL) { code_block = mmap((void *) 0x200000, CODE_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -115,6 +114,19 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) { ERR("%s", "Maximum Amount Of overwrite_calls() Uses Reached"); } _overwrite(NULL, -1, code_block, target); +} + +// Overwrite Specific BL Instruction +void _overwrite_call(const char *file, int line, void *start, void *target) { + update_code_block(target); + + uint32_t new_instruction = generate_bl_instruction(start, code_block); + _patch(file, line, start, (unsigned char *) &new_instruction); +} + +// Overwrite Function Calls +void _overwrite_calls(const char *file, int line, void *start, void *target) { + update_code_block(target); struct overwrite_data data; data.file = file; diff --git a/mods/src/extra.cpp b/mods/src/extra.cpp index 53b54625b..aa05e319d 100644 --- a/mods/src/extra.cpp +++ b/mods/src/extra.cpp @@ -93,7 +93,6 @@ extern "C" { } // Items - static unsigned char **item_sign = (unsigned char **) 0x17bba4; static unsigned char **item_flintAndSteel = (unsigned char **) 0x17ba70; static unsigned char **item_snowball = (unsigned char **) 0x17bbb0; static unsigned char **item_shears = (unsigned char **) 0x17bbf0; @@ -113,32 +112,46 @@ extern "C" { // Call Original int32_t ret = (*FillingContainer_addItem)(filling_container, item_instance); - // Add After Sign - if (*(int32_t *) (item_instance + 0x4) == *(int32_t *) (*item_sign + 0x4)) { - // Add Items - inventory_add_item(filling_container, *item_flintAndSteel, false); - inventory_add_item(filling_container, *item_snowball, false); - inventory_add_item(filling_container, *item_egg, false); - inventory_add_item(filling_container, *item_shears, false); - for (int i = 0; i < 15; i++) { - unsigned char *item_instance = (unsigned char *) ::operator new(0xc); - item_instance = (*ItemInstance_damage)(item_instance, *item_dye_powder, 1, i); - (*FillingContainer_addItem)(filling_container, item_instance); - } - // Add Tiles - inventory_add_item(filling_container, *tile_water, true); - inventory_add_item(filling_container, *tile_lava, true); - inventory_add_item(filling_container, *tile_calmWater, true); - inventory_add_item(filling_container, *tile_calmLava, true); - inventory_add_item(filling_container, *tile_glowingObsidian, true); - inventory_add_item(filling_container, *tile_topSnow, true); - inventory_add_item(filling_container, *tile_ice, true); - inventory_add_item(filling_container, *tile_invisible_bedrock, true); + // Add Items + inventory_add_item(filling_container, *item_flintAndSteel, false); + inventory_add_item(filling_container, *item_snowball, false); + inventory_add_item(filling_container, *item_egg, false); + inventory_add_item(filling_container, *item_shears, false); + for (int i = 0; i < 15; i++) { + unsigned char *item_instance = (unsigned char *) ::operator new(0xc); + item_instance = (*ItemInstance_damage)(item_instance, *item_dye_powder, 1, i); + (*FillingContainer_addItem)(filling_container, item_instance); } + // Add Tiles + inventory_add_item(filling_container, *tile_water, true); + inventory_add_item(filling_container, *tile_lava, true); + inventory_add_item(filling_container, *tile_calmWater, true); + inventory_add_item(filling_container, *tile_calmLava, true); + inventory_add_item(filling_container, *tile_glowingObsidian, true); + inventory_add_item(filling_container, *tile_topSnow, true); + inventory_add_item(filling_container, *tile_ice, true); + inventory_add_item(filling_container, *tile_invisible_bedrock, true); return ret; } + typedef void (*Minecraft_tick_t)(unsigned char *minecraft, int32_t param_1, int32_t param_2); + static Minecraft_tick_t Minecraft_tick = (Minecraft_tick_t) 0x16934; + + typedef void (*Textures_tick_t)(unsigned char *textures, bool param_1); + static Textures_tick_t Textures_tick = (Textures_tick_t) 0x531c4; + + static void Minecraft_tick_injection(unsigned char *minecraft, int32_t param_1, int32_t param_2) { + // Call Original Method + (*Minecraft_tick)(minecraft, param_1, param_2); + + // Tick Dynamic Textures + unsigned char *textures = *(unsigned char **) (minecraft + 0x164); + if (textures != NULL) { + (*Textures_tick)(textures, true); + } + } + __attribute((constructor)) static void init() { // Implement AppPlatform::AppPlatform_AppPlatform_readAssetFile So Translations Work overwrite((void *) 0x12b10, (void *) AppPlatform_readAssetFile); @@ -149,10 +162,14 @@ extern "C" { patch_address((void *) 0x10531c, (void *) Screen_updateEvents_injection); } - int is_server = extra_get_mode() == 2; - if (!is_server && extra_has_feature("Expand Creative Inventory")) { - // Add Extra Items To Creative Inventory - overwrite_calls((void *) FillingContainer_addItem, (void *) FillingContainer_addItem_injection); + if (extra_has_feature("Expand Creative Inventory")) { + // Add Extra Items To Creative Inventory (Only Replace Specific Function Call) + overwrite_call((void *) 0x8e0fc, (void *) FillingContainer_addItem_injection); + } + + if (extra_has_feature("Animated Watter")) { + // Tick Dynamic Textures (Animated Water) + overwrite_calls((void *) Minecraft_tick, (void *) Minecraft_tick_injection); } } }