diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d35964..bcc55a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,3 +123,8 @@ endif() if(BUILD_ARM_COMPONENTS) add_subdirectory(mods) endif() + +# Include Images +if(BUILD_NATIVE_COMPONENTS) + add_subdirectory(images) +endif() diff --git a/images/CMakeLists.txt b/images/CMakeLists.txt new file mode 100644 index 0000000..f10a1d0 --- /dev/null +++ b/images/CMakeLists.txt @@ -0,0 +1,10 @@ +project(images) + +# Title Background +if(NOT MCPI_SERVER_MODE) + install( + FILES "background.png" + DESTINATION "${MCPI_INSTALL_DIR}/data/images/gui" + RENAME "titleBG.png" + ) +endif() diff --git a/images/background.png b/images/background.png new file mode 100644 index 0000000..81af57a Binary files /dev/null and b/images/background.png differ diff --git a/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags b/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags index 9ae44ae..97d0d3a 100644 --- a/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags +++ b/launcher/data/client/lib/minecraft-pi-reborn-client/available-feature-flags @@ -33,3 +33,4 @@ FALSE Disable V-Sync TRUE Fix Options Screen FALSE Force Touch Inventory TRUE Fix Pause Menu +TRUE Improved Title Background diff --git a/launcher/src/bootstrap.c b/launcher/src/bootstrap.c index fefe576..f5ece47 100644 --- a/launcher/src/bootstrap.c +++ b/launcher/src/bootstrap.c @@ -209,10 +209,23 @@ void bootstrap(int argc, char *argv[]) { // Set MCPI_EXECUTABLE_PATH set_and_print_env("MCPI_EXECUTABLE_PATH", resolved_path); - // Set MCPI_DIRECTORY - chop_last_component(&resolved_path); - set_and_print_env("MCPI_DIRECTORY", resolved_path); - free(resolved_path); + // Set MCPI_VANILLA_ASSETS_PATH + { + chop_last_component(&resolved_path); + string_append(&resolved_path, "/data"); + set_and_print_env("MCPI_VANILLA_ASSETS_PATH", resolved_path); + free(resolved_path); + } + } + + // Set MCPI_REBORN_ASSETS_PATH + { + char *assets_path = realpath("/proc/self/exe", NULL); + ALLOC_CHECK(assets_path); + chop_last_component(&assets_path); + string_append(&assets_path, "/data"); + set_and_print_env("MCPI_REBORN_ASSETS_PATH", assets_path); + free(assets_path); } // Fix MCPI Dependencies diff --git a/libreborn/include/libreborn/exec.h b/libreborn/include/libreborn/exec.h index 9c1d5b3..9279522 100644 --- a/libreborn/include/libreborn/exec.h +++ b/libreborn/include/libreborn/exec.h @@ -26,9 +26,6 @@ char *get_binary_directory(); // Safe execvpe() Relative To Binary __attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const argv[], const char *const envp[]); -// Get MCPI Directory -char *get_mcpi_directory(); - // Run Command And Get Output char *run_command(const char *const command[], int *return_code); diff --git a/libreborn/include/libreborn/string.h b/libreborn/include/libreborn/string.h index 0ac9ba9..2d356a4 100644 --- a/libreborn/include/libreborn/string.h +++ b/libreborn/include/libreborn/string.h @@ -19,7 +19,7 @@ #define string_append(str, format, ...) \ { \ char *old = *str; \ - safe_asprintf(str, "%s" format, *str == NULL ? "" : *str, __VA_ARGS__); \ + safe_asprintf(str, "%s" format, *str == NULL ? "" : *str, ##__VA_ARGS__); \ ALLOC_CHECK(*str); \ if (old != NULL && old != *str) { \ free(old); \ diff --git a/libreborn/src/util/exec.c b/libreborn/src/util/exec.c index 6612712..adb2426 100644 --- a/libreborn/src/util/exec.c +++ b/libreborn/src/util/exec.c @@ -57,11 +57,6 @@ __attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const safe_execvpe(new_argv, envp); } -// Get MCPI Directory -char *get_mcpi_directory() { - return getenv("MCPI_DIRECTORY"); -} - // Run Command And Get Output char *run_command(const char *const command[], int *return_code) { // Store Output diff --git a/mods/src/home/home.c b/mods/src/home/home.c index 1474b8a..fa9610b 100644 --- a/mods/src/home/home.c +++ b/mods/src/home/home.c @@ -26,11 +26,8 @@ void init_home() { // Store Data In ~/.minecraft-pi Instead Of ~/.minecraft patch_address((void *) default_path, (void *) HOME_SUBDIRECTORY_FOR_GAME_DATA); - // Change Directory To Binary Directory Manually + // The override code resolves assets manually, + // making changing directory redundant. unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" patch((void *) 0xe0ac, nop_patch); - char *binary_directory = get_mcpi_directory(); - if (chdir(binary_directory) != 0) { - ERR("Unable To Change Directory: %s", strerror(errno)); - } } diff --git a/mods/src/misc/misc.cpp b/mods/src/misc/misc.cpp index 0948227..b4f366f 100644 --- a/mods/src/misc/misc.cpp +++ b/mods/src/misc/misc.cpp @@ -70,6 +70,15 @@ static void PauseScreen_init_injection(unsigned char *screen) { } } +// Improved Title Background +static void StartMenuScreen_render_Screen_renderBackground_injection(unsigned char *screen) { + // Draw + unsigned char *minecraft = *(unsigned char **) (screen + Screen_minecraft_property_offset); + unsigned char *textures = *(unsigned char **) (minecraft + Minecraft_textures_property_offset); + (*Textures_loadAndBindTexture)(textures, "gui/titleBG.png"); + (*GuiComponent_blit)(screen, 0, 0, 0, 0, *(int32_t *) (screen + Screen_width_property_offset), *(int32_t *) (screen + Screen_height_property_offset), 0x100, 0x100); +} + // Init void _init_misc_cpp() { // Implement AppPlatform::readAssetFile So Translations Work @@ -85,4 +94,14 @@ void _init_misc_cpp() { // Add Missing Buttons To Pause Menu patch_address(PauseScreen_init_vtable_addr, (void *) PauseScreen_init_injection); } + + // Improved Title Background + if (feature_has("Improved Title Background", server_disabled)) { + // Switch Background + overwrite_call((void *) 0x39528, (void *) StartMenuScreen_render_Screen_renderBackground_injection); + overwrite_call((void *) 0x3dee0, (void *) StartMenuScreen_render_Screen_renderBackground_injection); + // Text Color + patch_address((void *) 0x397ac, (void *) 0xffffffff); + patch_address((void *) 0x3e10c, (void *) 0xffffffff); + } } diff --git a/mods/src/options/options.c b/mods/src/options/options.c index 870448f..8b6af11 100644 --- a/mods/src/options/options.c +++ b/mods/src/options/options.c @@ -50,13 +50,6 @@ static void Options_initDefaultValue_injection(unsigned char *options) { // Call Original Method (*Options_initDefaultValue)(options); - // Enable Crosshair In Touch GUI - *(options + Options_split_controls_property_offset) = 1; - // 3D Anaglyph - *(options + Options_3d_anaglyph_property_offset) = anaglyph; - // Render Distance - *(int32_t *) (options + Options_render_distance_property_offset) = render_distance; - // Default Graphics Settings *(options + Options_fancy_graphics_property_offset) = 1; *(options + Options_ambient_occlusion_property_offset) = 1; @@ -64,6 +57,18 @@ static void Options_initDefaultValue_injection(unsigned char *options) { // Store stored_options = options; } +static void Minecraft_init_injection(unsigned char *minecraft) { + // Call Original Method + (*Minecraft_init)(minecraft); + + unsigned char *options = minecraft + Minecraft_options_property_offset; + // Enable Crosshair In Touch GUI + *(options + Options_split_controls_property_offset) = 1; + // 3D Anaglyph + *(options + Options_3d_anaglyph_property_offset) = anaglyph; + // Render Distance + *(int32_t *) (options + Options_render_distance_property_offset) = render_distance; +} // Smooth Lighting static void TileRenderer_tesselateBlockInWorld_injection(unsigned char *tile_renderer, unsigned char *tile, int32_t x, int32_t y, int32_t z) { @@ -93,6 +98,7 @@ void init_options() { // Set Options overwrite_calls((void *) Options_initDefaultValue, (void *) Options_initDefaultValue_injection); + overwrite_calls((void *) Minecraft_init, (void *) Minecraft_init_injection); // Change Username const char *username = get_username(); diff --git a/mods/src/override/override.c b/mods/src/override/override.c index d4d567a..7a562ea 100644 --- a/mods/src/override/override.c +++ b/mods/src/override/override.c @@ -8,8 +8,23 @@ #include +#include "override.h" #include "../home/home.h" +// Hook access +HOOK(access, int, (const char *pathname, int mode)) { + char *new_path = override_get_path(pathname); + // Open File + ensure_access(); + int ret = (*real_access)(new_path != NULL ? new_path : pathname, mode); + // Free Data + if (new_path != NULL) { + free(new_path); + } + // Return + return ret; +} + // Get Override Path For File (If It Exists) char *override_get_path(const char *filename) { // Get MCPI Home Path @@ -18,43 +33,45 @@ char *override_get_path(const char *filename) { char *overrides = NULL; safe_asprintf(&overrides, "%s/overrides", home_path); - // Get Data Path - char *data = NULL; - char *binary_directory = get_mcpi_directory(); - safe_asprintf(&data, "%s/data", binary_directory); - int data_length = strlen(data); + // Data Prefiix + char *data_prefix = "data/"; + int data_prefix_length = strlen(data_prefix); - // Get Full Path - char *full_path; - if (strlen(filename) > 0 && filename[0] == '/') { - // Absolute Path - full_path = strdup(filename); - } else { - // Relative Path - full_path = realpath(filename, NULL); - } + // Folders To Check + char *asset_folders[] = { + overrides, + getenv("MCPI_REBORN_ASSETS_PATH"), + getenv("MCPI_VANILLA_ASSETS_PATH"), + NULL + }; // Check For Override char *new_path = NULL; - if (full_path != NULL) { - if (starts_with(full_path, data)) { - safe_asprintf(&new_path, "%s%s", overrides, &full_path[data_length]); - if (access(new_path, F_OK) == -1) { + if (starts_with(filename, data_prefix)) { + // Test Asset Folders + for (int i = 0; asset_folders[i] != NULL; i++) { + safe_asprintf(&new_path, "%s/%s", asset_folders[i], &filename[data_prefix_length]); + ensure_access(); + if ((*real_access)(new_path, F_OK) == -1) { + // Not Found In Asset Folder free(new_path); new_path = NULL; + continue; + } else { + // Found + break; } } - free(full_path); } - // Free Variables + // Free free(overrides); - free(data); // Return return new_path; } +// Hook fopen HOOK(fopen, FILE *, (const char *filename, const char *mode)) { char *new_path = override_get_path(filename); // Open File @@ -68,6 +85,7 @@ HOOK(fopen, FILE *, (const char *filename, const char *mode)) { return file; } +// Hook fopen64 HOOK(fopen64, FILE *, (const char *filename, const char *mode)) { char *new_path = override_get_path(filename); // Open File diff --git a/mods/src/sound/sound.cpp b/mods/src/sound/sound.cpp index f8c9712..ea7c8b4 100644 --- a/mods/src/sound/sound.cpp +++ b/mods/src/sound/sound.cpp @@ -22,31 +22,29 @@ std::string _sound_get_source_file() { } else { // Resolve - // Get Binary Directory - char *binary_directory = get_mcpi_directory(); - // Get Full Path - char *full_path = NULL; - safe_asprintf(&full_path, "%s/" SOURCE_FILE_BASE, binary_directory); + // Get Path + char *path = strdup(SOURCE_FILE_BASE); + ALLOC_CHECK(path); // Handle Overrides - char *overridden_full_path = override_get_path(full_path); + char *overridden_full_path = override_get_path(path); if (overridden_full_path != NULL) { - free(full_path); - full_path = overridden_full_path; + free(path); + path = overridden_full_path; } // Check If Sound Exists - if (access(full_path, F_OK) == -1) { + if (access(path, F_OK) == -1) { // Fail WARN("Audio Source File Doesn't Exist: " SOURCE_FILE_BASE); source.assign(""); } else { // Set - source.assign(full_path); + source.assign(path); } // Free - free(full_path); + free(path); // Mark As Loaded source_loaded = true; diff --git a/symbols/include/symbols/minecraft.h b/symbols/include/symbols/minecraft.h index e299545..22def5b 100644 --- a/symbols/include/symbols/minecraft.h +++ b/symbols/include/symbols/minecraft.h @@ -467,6 +467,11 @@ static uint32_t FurnaceScreen_tile_entity_property_offset = 0x1d0; // FurnaceTil typedef ItemInstance *(*FurnaceTileEntity_getItem_t)(unsigned char *furnace_tile_entity, int32_t slot); static uint32_t FurnaceTileEntity_getItem_vtable_offset = 0x2c; +// GuiComponent + +typedef void (*GuiComponent_blit_t)(unsigned char *component, int32_t param_1, int32_t param_2, int32_t param_3, int32_t param_4, int32_t param_5, int32_t param_6, int32_t param_7, int32_t param_8); +static GuiComponent_blit_t GuiComponent_blit = (GuiComponent_blit_t) 0x282a4; + // Screen typedef void (*Screen_updateEvents_t)(unsigned char *screen); @@ -482,11 +487,15 @@ typedef void (*Screen_init_t)(unsigned char *screen); typedef void (*Screen_tick_t)(unsigned char *screen); +typedef void (*Screen_render_t)(unsigned char *screen, int32_t param_1, int32_t param_2, float param_3); + typedef int32_t (*Screen_handleBackEvent_t)(unsigned char *screen, bool param_1); static uint32_t Screen_minecraft_property_offset = 0x14; // Minecraft * static uint32_t Screen_rendered_buttons_property_offset = 0x18; // std::vector