Compare commits

...

13 Commits

Author SHA1 Message Date
0592db9bdf 2.3.2
All checks were successful
minecraft-pi-reborn/pipeline/head This commit looks good
2022-03-25 21:20:34 -04:00
3fee57ce60 Fix Missing Comment 2022-03-25 21:09:29 -04:00
b3c32b211b Add Grass To Expanded Creative Inventory 2022-03-25 21:07:28 -04:00
ea92e5188e Add Nether Reactor Stages To Expanded Creative Inventory 2022-03-25 00:35:06 -04:00
9a4b70b5ca Improve Temporary File Improving 2022-03-24 23:03:59 -04:00
b5974f3f46 Simplify Launch Process 2022-03-24 22:47:34 -04:00
709de17558 Fix Nether Reactor With Creative Restrictions Disabled 2022-03-23 19:26:49 -04:00
3894e98a04 2022! 2022-03-18 23:56:27 -04:00
bf890d190b Sort Feature Flags 2022-03-16 19:51:45 -04:00
a40da62b70 Speedup run_command 2022-03-16 19:51:33 -04:00
59b8fd9f54 Make iterate_text_sections MCPI-Agnostic 2022-03-16 19:50:46 -04:00
55a815643b Add "Disable V-Sync" Feature Flag 2022-03-16 19:49:13 -04:00
aa471fb4ba Update Zenity 2022-03-16 19:48:37 -04:00
35 changed files with 362 additions and 273 deletions

View File

@ -41,7 +41,6 @@ endif()
set(MCPI_INSTALL_DIR "lib/${MCPI_VARIANT_NAME}")
set(MCPI_LIB_DIR "${MCPI_INSTALL_DIR}/lib")
set(MCPI_BIN_DIR "${MCPI_INSTALL_DIR}/bin")
set(MCPI_FALLBACK_LIB_DIR "${MCPI_INSTALL_DIR}/fallback-lib")
# Build Mode
if(NOT CMAKE_BUILD_TYPE)

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 TheBrokenRail
Copyright (c) 2022 TheBrokenRail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1 +1 @@
2.3.1
2.3.2

@ -1 +1 @@
Subproject commit 1461c59aa2426b25503102e62bc8f4b65e079c5f
Subproject commit 955fbd9d265fa95adf9cb94896eb9a516aa50420

@ -1 +1 @@
Subproject commit b01f0001eae0b01f9de2bba3d1b93c386b298c0d
Subproject commit cdcc55e55f08956f6c5a5f3d63fce4614c75e8d4

View File

@ -1,5 +1,12 @@
# Changelog
**2.3.2**
* Simplify Launch Sequence
* Add More Blocks To Expanded Creative Inventory
* Fix Nether Reactor With Creative Restrictions Disabled
* Alphabetize Feature Flags
* Add ``Disable V-Sync`` Feature Flag (Disabled By Default)
**2.3.1**
* Internal Refactor Of ``libreborn``
* Remove Use Of ``/bin/sh``

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -2,7 +2,7 @@ project(launcher)
# Launcher
if(BUILD_NATIVE_COMPONENTS)
add_executable(launcher src/bootstrap.c src/ldconfig.cpp)
add_executable(launcher src/bootstrap.c src/patchelf.c)
if(MCPI_SERVER_MODE)
target_sources(launcher PRIVATE src/server/launcher.c)
else()

View File

@ -33,3 +33,4 @@ FALSE Disable Raw Mouse Motion (Not Recommended)
TRUE Fix Furnace Not Checking Item Auxiliary
FALSE Disable Hosting LAN Worlds
TRUE Improved Cursor Rendering
FALSE Disable V-Sync

View File

@ -11,7 +11,7 @@
#include <libreborn/libreborn.h>
#include "bootstrap.h"
#include "ldconfig.h"
#include "patchelf.h"
// Set Environmental Variable
#define PRESERVE_ENVIRONMENTAL_VARIABLE(name) \
@ -34,7 +34,7 @@ static void trim(char **value) {
void set_and_print_env(const char *name, char *value) {
// Set Variable With No Trailing Colon
static const char *unmodified_name_prefix = "MCPI_";
if (strncmp(unmodified_name_prefix, name, strlen(unmodified_name_prefix)) != 0) {
if (!starts_with(name, unmodified_name_prefix)) {
trim(&value);
}
@ -194,8 +194,57 @@ void bootstrap(int argc, char *argv[]) {
usr_prefix = "";
}
// Resolve Binary Path & Set MCPI_DIRECTORY
{
// Log
DEBUG("%s", "Resolving File Paths...");
// Resolve Full Binary Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/" MCPI_BINARY, binary_directory);
char *resolved_path = realpath(full_path, NULL);
ALLOC_CHECK(resolved_path);
free(full_path);
// 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);
}
// Fix MCPI Dependencies
{
// Log
DEBUG("%s", "Patching ELF Dependencies...");
// Find Linker
char *linker = NULL;
#ifndef __arm__
safe_asprintf(&linker, "%s/usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3", usr_prefix);
#else
safe_asprintf(&linker, "/lib/ld-linux-armhf.so.3");
#endif
// Patch
patch_mcpi_elf_dependencies(linker);
// Free Linker Path
free(linker);
// Verify
if (!starts_with(getenv("MCPI_EXECUTABLE_PATH"), "/tmp")) {
IMPOSSIBLE();
}
}
// Configure LD_LIBRARY_PATH
{
// Log
DEBUG("%s", "Setting Linker Search Paths...");
// Preserve
PRESERVE_ENVIRONMENTAL_VARIABLE("LD_LIBRARY_PATH");
char *new_ld_path = NULL;
@ -203,38 +252,16 @@ void bootstrap(int argc, char *argv[]) {
// Add Library Directory
safe_asprintf(&new_ld_path, "%s/lib", binary_directory);
// Add MCPI_LD_LIBRARY_PATH
{
char *value = get_env_safe("MCPI_LD_LIBRARY_PATH");
if (strlen(value) > 0) {
string_append(&new_ld_path, ":%s", value);
}
}
// Load ARM Libraries (Ensure Priority)
string_append(&new_ld_path, ":%s/usr/lib/arm-linux-gnueabihf:%s/usr/arm-linux-gnueabihf/lib", usr_prefix, usr_prefix);
// Add LD_LIBRARY_PATH (ARM32 Only)
#ifdef __arm__
{
char *value = get_env_safe("LD_LIBRARY_PATH");
if (strlen(value) > 0) {
string_append(&new_ld_path, ":%s", value);
}
}
#endif
// Load ARM Libraries (Ensure Priority)
string_append(&new_ld_path, ":%s/usr/lib/arm-linux-gnueabihf:%s/usr/arm-linux-gnueabihf/lib", usr_prefix, usr_prefix);
// Add Full Library Search Path
{
char *value = get_full_library_search_path();
if (strlen(value) > 0) {
string_append(&new_ld_path, ":%s", value);
}
free(value);
}
// Add Fallback Library Directory
string_append(&new_ld_path, ":%s/fallback-lib", binary_directory);
// Set And Free
set_and_print_env("LD_LIBRARY_PATH", new_ld_path);
@ -243,6 +270,9 @@ void bootstrap(int argc, char *argv[]) {
// Configure LD_PRELOAD
{
// Log
DEBUG("%s", "Locating Mods...");
// Preserve
PRESERVE_ENVIRONMENTAL_VARIABLE("LD_PRELOAD");
char *new_ld_preload = NULL;
@ -292,24 +322,6 @@ void bootstrap(int argc, char *argv[]) {
free(new_ld_preload);
}
// Resolve Binary Path & Set MCPI_DIRECTORY
{
// Resolve Full Binary Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/" MCPI_BINARY, binary_directory);
char *resolved_path = realpath(full_path, NULL);
ALLOC_CHECK(resolved_path);
free(full_path);
// 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);
}
// Free Binary Directory
free(binary_directory);
@ -317,8 +329,8 @@ void bootstrap(int argc, char *argv[]) {
INFO("%s", "Starting Game...");
// Arguments
int argv_start = 2; // argv = &new_args[argv_start]
const char *new_args[argv_start /* 2 Potential Prefix Arguments (QEMU And Linker) */ + argc + 1 /* NULL-Terminator */]; //
int argv_start = 1; // argv = &new_args[argv_start]
const char *new_args[argv_start /* 1 Potential Prefix Argument (QEMU) */ + argc + 1 /* NULL-Terminator */]; //
// Copy Existing Arguments
for (int i = 1; i < argc; i++) {
@ -330,13 +342,6 @@ void bootstrap(int argc, char *argv[]) {
// Set Executable Argument
new_args[argv_start] = getenv("MCPI_EXECUTABLE_PATH");
// Non-ARM32 Systems Need Manually Specified Linker
#ifndef __arm__
argv_start--;
char *linker = NULL;
safe_asprintf(&linker, "%s/usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3", usr_prefix);
new_args[argv_start] = linker;
// Non-ARM Systems Need QEMU
#ifndef __ARM_ARCH
argv_start--;
@ -345,7 +350,6 @@ void bootstrap(int argc, char *argv[]) {
// Prevent QEMU From Being Modded
PASS_ENVIRONMENTAL_VARIABLE_TO_QEMU("LD_LIBRARY_PATH");
PASS_ENVIRONMENTAL_VARIABLE_TO_QEMU("LD_PRELOAD");
#endif
#endif
// Run

View File

@ -5,11 +5,36 @@
#include <sys/stat.h>
#include <vector>
#include <functional>
#include <algorithm>
#include <libreborn/libreborn.h>
#include "../bootstrap.h"
// Strip Feature Flag Default
static std::string strip_feature_flag_default(std::string flag, bool *default_ret) {
// Valid Values
std::string true_str = "TRUE ";
std::string false_str = "FALSE ";
// Test
if (flag.rfind(true_str, 0) == 0) {
// Enabled By Default
if (default_ret != NULL) {
*default_ret = true;
}
return flag.substr(true_str.length(), std::string::npos);
} else if (flag.rfind(false_str, 0) == 0) {
// Disabled By Default
if (default_ret != NULL) {
*default_ret = false;
}
return flag.substr(false_str.length(), std::string::npos);
} else {
// Invalid
ERR("%s", "Invalid Feature Flag Default");
}
}
// Load Available Feature Flags
static void load_available_feature_flags(std::function<void(std::string)> callback) {
// Get Path
@ -19,18 +44,35 @@ static void load_available_feature_flags(std::function<void(std::string)> callba
// Load File
std::ifstream stream(path);
if (stream && stream.good()) {
std::string line;
while (std::getline(stream, line)) {
if (line.length() > 0) {
// Verify Line
if (line.find('|') == std::string::npos) {
callback(line);
} else {
// Invalid Line
ERR("%s", "Feature Flag Contains Invalid '|'");
std::vector<std::string> lines;
// Read File
{
std::string line;
while (std::getline(stream, line)) {
if (line.length() > 0) {
// Verify Line
if (line.find('|') == std::string::npos) {
lines.push_back(line);
} else {
// Invalid Line
ERR("%s", "Feature Flag Contains Invalid '|'");
}
}
}
}
// Sort
std::sort(lines.begin(), lines.end(), [](std::string a, std::string b) {
// Strip Defaults
std::string stripped_a = strip_feature_flag_default(a, NULL);
std::string stripped_b = strip_feature_flag_default(b, NULL);
// Sort
return stripped_a < stripped_b;
});
// Run Callbacks
for (std::string line : lines) {
callback(line);
}
// Close File
stream.close();
} else {
ERR("%s", "Unable To Load Available Feature Flags");
@ -130,18 +172,20 @@ int main(int argc, char *argv[]) {
command.push_back("Enabled");
command.push_back("--column");
command.push_back("Feature");
load_available_feature_flags([&command](std::string line) {
if (line.rfind("TRUE ", 0) == 0) {
load_available_feature_flags([&command](std::string flag) {
bool default_value;
// Strip Default Value
std::string stripped_flag = strip_feature_flag_default(flag, &default_value);
// Specify Default Value
if (default_value) {
// Enabled By Default
command.push_back("TRUE");
command.push_back(line.substr(5, std::string::npos));
} else if (line.rfind("FALSE ", 0) == 0) {
} else {
// Disabled By Default
command.push_back("FALSE");
command.push_back(line.substr(6, std::string::npos));
} else {
ERR("%s", "Invalid Feature Flag Default");
}
// Specify Name
command.push_back(stripped_flag);
});
// Run
run_zenity_and_set_env("MCPI_FEATURE_FLAGS", command);

View File

@ -1,57 +0,0 @@
#include <unistd.h>
#include <string>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <libreborn/libreborn.h>
#include "ldconfig.h"
char *get_full_library_search_path() {
std::string processed_output;
// Run
int return_code;
const char *ldconfig_argv[] = {"/sbin/ldconfig", "-NXv", NULL};
char *output = run_command(ldconfig_argv, &return_code);
std::stringstream output_stream((std::string(output)));
// Check Exit Code
if (return_code != 0) {
ERR("ldconfig Failed: Exit Code: %i", return_code);
}
// Read
int running = 1;
while (running) {
std::string line;
if (std::getline(output_stream, line)) {
// Remove Newline
if (line.size() > 0 && line[line.size() - 1] == '\n') {
line.pop_back();
}
// Interpret
if (line.size() >= 2 && line[0] != '\t' && line[line.size() - 1] == ':') {
// Blacklist RPI Legacy GL Drivers
#define RPI_LEGACY_GL_PATH "/opt/vc"
if (line.rfind(RPI_LEGACY_GL_PATH ":", 0) != 0 && line.rfind(RPI_LEGACY_GL_PATH "/", 0) != 0) {
processed_output.append(line);
}
}
} else {
running = 0;
}
}
// Free Output
free(output);
// Remove Colon
if (processed_output.size() > 0 && processed_output[processed_output.size() - 1] == ':') {
processed_output.pop_back();
}
// Return
char *output_str = strdup(processed_output.c_str());
ALLOC_CHECK(output_str);
return output_str;
}

90
launcher/src/patchelf.c Normal file
View File

@ -0,0 +1,90 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <libreborn/libreborn.h>
#include "bootstrap.h"
#include "patchelf.h"
// Duplicate MCPI Executable Into /tmp
static void duplicate_mcpi_executable() {
// Get Original Path
const char *original_path = getenv("MCPI_EXECUTABLE_PATH");
// Generate New File
char new_path[] = "/tmp/.minecraft-pi-XXXXXX";
int new_file_fd = mkstemp(new_path);
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));
}
FILE *new_file = fdopen(new_file_fd, "wb");
if (new_file == NULL) {
ERR("Unable To Open Temporary File: %s", strerror(errno));
}
set_and_print_env("MCPI_EXECUTABLE_PATH", new_path);
// Copy Original File
{
// Open Original File
FILE *original_file = fopen(original_path, "rb");
if (original_file == NULL) {
ERR("Unable To Open File: %s", original_path);
}
// Copy
#define BUFFER_SIZE 1024
char buf[BUFFER_SIZE];
size_t bytes_read = 0;
while ((bytes_read = fread((void *) buf, 1, BUFFER_SIZE, original_file)) > 0) {
fwrite((void *) buf, 1, bytes_read, new_file);
if (ferror(new_file) != 0) {
ERR("Unable To Write File: %s", new_path);
}
}
if (ferror(original_file) != 0) {
ERR("Unable To Read File: %s", original_path);
}
// Close Original File
fclose(original_file);
}
// Close New File
fclose(new_file);
close(new_file_fd);
}
// Fix MCPI Dependencies
void patch_mcpi_elf_dependencies(const char *linker) {
// Duplicate MCPI executable into /tmp so it can be modified.
duplicate_mcpi_executable();
// Get Path
char *exe = getenv("MCPI_EXECUTABLE_PATH");
// Run patchelf
const char *const command[] = {
"patchelf",
"--set-interpreter", linker,
"--remove-needed", "libbcm_host.so",
"--remove-needed", "libX11.so.6",
"--remove-needed", "libEGL.so",
"--replace-needed", "libGLESv2.so", "libGLESv1_CM.so.1",
exe,
NULL
};
int return_code = 0;
char *output = run_command(command, &return_code);
if (output != NULL) {
free(output);
}
if (return_code != 0) {
ERR("patchelf Failed: Exit Code: %i", return_code);
}
// Fix Permissions
if (chmod(exe, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", exe, strerror(errno));
}
}

View File

@ -4,7 +4,7 @@
extern "C" {
#endif
char *get_full_library_search_path(); // Remember To free()
void patch_mcpi_elf_dependencies(const char *linker);
#ifdef __cplusplus
}

View File

@ -15,7 +15,7 @@ extern "C" {
// Find And Iterate Over All .text Sections In Current Binary
typedef void (*text_section_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data);
void iterate_text_sections(text_section_callback_t callback, void *data);
void iterate_text_sections(const char *exe, text_section_callback_t callback, void *data);
#ifdef __cplusplus
}

View File

@ -33,6 +33,9 @@ extern "C" {
// Sanitize String
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
// Starts With
int starts_with(const char *str, const char *prefix);
#ifdef __cplusplus
}
#endif

View File

@ -115,7 +115,7 @@ void _overwrite_calls(const char *file, int line, void *start, void *target) {
data.replacement = code_block;
data.found = 0;
iterate_text_sections(overwrite_calls_callback, &data);
iterate_text_sections("/proc/self/exe", overwrite_calls_callback, &data);
// Increment Code Block Position
increment_code_block();

View File

@ -1,13 +1,13 @@
#include <libreborn/elf.h>
// Find And Iterate Over All .text Sections In Current Binary
void iterate_text_sections(text_section_callback_t callback, void *data) {
void iterate_text_sections(const char *exe, text_section_callback_t callback, void *data) {
// Load Main Binary
FILE *file_obj = fopen(getenv("MCPI_EXECUTABLE_PATH"), "rb");
FILE *file_obj = fopen(exe, "rb");
// Verify Binary
if (!file_obj) {
ERR("%s", "Unable To Open Current Binary");
ERR("%s", "Unable To Open Binary");
}
// Get File Size

View File

@ -95,17 +95,19 @@ char *run_command(const char *const command[], int *return_code) {
// Read stdout
close(output_pipe[1]);
char *output = NULL;
char c;
int bytes_read = 0;
while ((bytes_read = read(output_pipe[0], (void *) &c, 1)) > 0) {
string_append(&output, "%c", c);
#define BUFFER_SIZE 1024
char buf[BUFFER_SIZE];
size_t bytes_read = 0;
while ((bytes_read = read(output_pipe[0], (void *) buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */)) > 0) {
buf[bytes_read] = '\0';
string_append(&output, "%s", buf);
}
close(output_pipe[0]);
// Get Return Code
int status;
waitpid(ret, &status, 0);
*return_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
*return_code = WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE;
// Return
return output;

View File

@ -23,3 +23,8 @@ void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
}
}
}
// Starts With
int starts_with(const char *str, const char *prefix) {
return strncmp(prefix, str, strlen(prefix)) == 0;
}

View File

@ -7,31 +7,8 @@ set_target_properties(GLESv1_CM PROPERTIES SOVERSION "1")
# Stubs Only Needed For ARM
if(BUILD_ARM_COMPONENTS)
# Stub RPI-Specific Graphics
add_library(bcm_host SHARED src/bcm_host.c)
# Install
install(TARGETS bcm_host DESTINATION "${MCPI_LIB_DIR}")
# Stub EGL
add_library(EGL SHARED src/EGL.c)
target_link_libraries(EGL reborn-util media-layer-headers)
set_target_properties(EGL PROPERTIES SOVERSION "1")
# Stub X11
add_library(X11 SHARED src/X11.c)
target_link_libraries(X11 reborn-util media-layer-headers)
set_target_properties(X11 PROPERTIES SOVERSION "6")
# Install
if(MCPI_HEADLESS_MODE OR MCPI_USE_MEDIA_LAYER_PROXY)
install(TARGETS EGL X11 DESTINATION "${MCPI_LIB_DIR}")
else()
install(TARGETS EGL X11 DESTINATION "${MCPI_FALLBACK_LIB_DIR}") # Place At The End Of LD_LIBRARY_PATH
endif()
# Install Fake GLESv1_CM Stubs In Server Mode
if(MCPI_HEADLESS_MODE)
install(TARGETS GLESv1_CM DESTINATION "${MCPI_LIB_DIR}")
endif()
# Redirect MCPI To Correct Libraries
add_subdirectory(redirect)
endif()

View File

@ -1,18 +0,0 @@
project(media-layer-stubs-redirect)
# MCPI Depends On GLESv2, But Uses GLESv1_CM
add_library(GLESv2_redirect SHARED src/nop.c)
target_link_libraries(GLESv2_redirect GLESv1_CM)
target_link_options(GLESv2_redirect PRIVATE "-Wl,--no-as-needed")
set_target_properties(GLESv2_redirect PROPERTIES OUTPUT_NAME "GLESv2")
install(TARGETS GLESv2_redirect DESTINATION "${MCPI_LIB_DIR}")
# MCPI links to libEGL.so instead of libEGL.so.1, this creates a fake libEGL.so which redirects it to the correct libEGL.so.1.
# This is only needed on configurations that don't generate their own libEGL.so.
if(NOT MCPI_HEADLESS_MODE AND NOT MCPI_USE_MEDIA_LAYER_PROXY)
add_library(EGL_redirect SHARED src/nop.c)
target_link_libraries(EGL_redirect EGL)
target_link_options(EGL_redirect PRIVATE "-Wl,--no-as-needed")
set_target_properties(EGL_redirect PROPERTIES OUTPUT_NAME "EGL")
install(TARGETS EGL_redirect DESTINATION "${MCPI_LIB_DIR}")
endif()

View File

@ -1 +0,0 @@
// NOP

View File

@ -1,39 +0,0 @@
#include <EGL/egl.h>
#include <libreborn/libreborn.h>
// EGL Is Replaced With GLFW
EGLDisplay eglGetDisplay(__attribute__((unused)) NativeDisplayType native_display) {
IMPOSSIBLE();
}
EGLBoolean eglInitialize(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint *major, __attribute__((unused)) EGLint *minor) {
IMPOSSIBLE();
}
EGLBoolean eglChooseConfig(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint const *attrib_list, __attribute__((unused)) EGLConfig *configs, __attribute__((unused)) EGLint config_size, __attribute__((unused)) EGLint *num_config) {
IMPOSSIBLE();
}
EGLBoolean eglBindAPI(__attribute__((unused)) EGLenum api) {
IMPOSSIBLE();
}
EGLContext eglCreateContext(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list) {
IMPOSSIBLE();
}
EGLSurface eglCreateWindowSurface(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list) {
IMPOSSIBLE();
}
EGLBoolean eglMakeCurrent(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface draw, __attribute__((unused)) EGLSurface read, __attribute__((unused)) EGLContext context) {
IMPOSSIBLE();
}
EGLBoolean eglDestroySurface(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
IMPOSSIBLE();
}
EGLBoolean eglDestroyContext(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLContext context) {
IMPOSSIBLE();
}
EGLBoolean eglTerminate(__attribute__((unused)) EGLDisplay display) {
IMPOSSIBLE();
}
EGLBoolean eglSwapBuffers(__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface) {
IMPOSSIBLE();
}

View File

@ -1,12 +0,0 @@
#include <X11/Xlib.h>
#include <libreborn/libreborn.h>
// Raw X11 Is Replaced With GLFW
int XTranslateCoordinates(__attribute__((unused)) void *display, __attribute__((unused)) XID src_w, __attribute__((unused)) XID dest_w, __attribute__((unused)) int src_x, __attribute__((unused)) int src_y, __attribute__((unused)) int *dest_x_return, __attribute__((unused)) int *dest_y_return, __attribute__((unused)) XID *child_return) {
IMPOSSIBLE();
}
int XGetWindowAttributes(__attribute__((unused)) void *display, __attribute__((unused)) XID w, __attribute__((unused)) XWindowAttributes *window_attributes_return) {
IMPOSSIBLE();
}

View File

@ -1,27 +0,0 @@
#include <stdint.h>
void bcm_host_init(void) {
}
void bcm_host_deinit(void) {
}
int32_t graphics_get_display_size(__attribute__((unused)) const uint16_t display_number, __attribute__((unused)) uint32_t *width, __attribute__((unused)) uint32_t *height) {
return -1;
}
uint32_t vc_dispmanx_display_open(__attribute__((unused)) uint32_t device) {
return 0;
}
uint32_t vc_dispmanx_element_add(__attribute__((unused)) uint32_t update, __attribute__((unused)) uint32_t display, __attribute__((unused)) int32_t layer, __attribute__((unused)) const void *dest_rect, __attribute__((unused)) uint32_t src, __attribute__((unused)) const void *src_rect, __attribute__((unused)) uint32_t protection, __attribute__((unused)) void *alpha, __attribute__((unused)) void *clamp, __attribute__((unused)) uint32_t transform) {
return 0;
}
uint32_t vc_dispmanx_update_start(__attribute__((unused)) int32_t priority) {
return 0;
}
int vc_dispmanx_update_submit_sync(__attribute__((unused)) uint32_t update) {
return 0;
}

View File

@ -7,7 +7,7 @@ add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
## Mods
add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c)
add_library(compat SHARED src/compat/compat.c src/compat/egl.c src/compat/x11.c src/compat/bcm_host.c)
target_link_libraries(compat reborn-patch media-layer-core)
add_library(readdir SHARED src/readdir/readdir.c)

View File

@ -0,0 +1,18 @@
#include <libreborn/libreborn.h>
// Do Nothing Function
static void do_nothing() {
// NOP
}
// Patch bcm_host Calls
__attribute__((constructor)) static void patch_bcm_host_calls() {
// Disable bcm_host Calls
overwrite_call((void *) 0xdfec, (void *) do_nothing); // bcm_host_init
overwrite_call((void *) 0x12418, (void *) do_nothing); // bcm_host_deinit
overwrite_call((void *) 0x125a8, (void *) do_nothing); // graphics_get_display_size
overwrite_call((void *) 0x125dc, (void *) do_nothing); // vc_dispmanx_display_open
overwrite_call((void *) 0x125e8, (void *) do_nothing); // vc_dispmanx_update_start
overwrite_call((void *) 0x12618, (void *) do_nothing); // vc_dispmanx_element_add
overwrite_call((void *) 0x12624, (void *) do_nothing); // vc_dispmanx_update_submit_sync
}

View File

@ -1,14 +1,16 @@
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include "compat.h"
#include "../init/init.h"
#include <libreborn/libreborn.h>
#ifndef MCPI_SERVER_MODE
#include <SDL/SDL.h>
#include <media-layer/core.h>
#include <libreborn/libreborn.h>
#include "../input/input.h"
#include "../sign/sign.h"
@ -119,6 +121,21 @@ void init_compat() {
signal(SIGTERM, exit_handler);
}
// Cleanup Temporary Files
__attribute__((destructor)) static void cleanup_temporary() {
// Cleanup Executable
{
const char *exe = getenv("MCPI_EXECUTABLE_PATH");
// Check If Executable Is Temporary
if (exe != NULL && starts_with(exe, "/tmp")) {
// Cleanup Temporary File
if (unlink(exe) != 0) {
ERR("Unable To Cleanup Temporary File: %s", strerror(errno));
}
}
}
}
// Store Exit Requests
static int exit_requested = 0;
int compat_check_exit_requested() {

View File

@ -48,10 +48,48 @@ static int32_t Inventory_setupDefault_FillingContainer_addItem_call_injection(un
inventory_add_item(filling_container, *Tile_bedrock, true);
inventory_add_item(filling_container, *Tile_info_updateGame1, true);
inventory_add_item(filling_container, *Tile_info_updateGame2, true);
// Nether Reactor
for (int i = 0; i < 3; i++) {
if (i == 0) {
// Default Is Already In The Creative Inventory
continue;
}
ItemInstance *new_item_instance = new ItemInstance;
ALLOC_CHECK(new_item_instance);
new_item_instance = (*ItemInstance_constructor_tile_extra)(new_item_instance, *Tile_netherReactor, 1, i);
(*FillingContainer_addItem)(filling_container, new_item_instance);
}
// Tall Grass
for (int i = 0; i < 4; i++) {
if (i == 2) {
// Identical To Previous Auxiliary Value
continue;
}
ItemInstance *new_item_instance = new ItemInstance;
ALLOC_CHECK(new_item_instance);
new_item_instance = (*ItemInstance_constructor_tile_extra)(new_item_instance, *Tile_tallgrass, 1, i);
(*FillingContainer_addItem)(filling_container, new_item_instance);
}
return ret;
}
// Hook Specific TileItem Constructor
static unsigned char *Tile_initTiles_TileItem_injection(unsigned char *tile_item, int32_t id) {
// Call Original Method
unsigned char *ret = (*TileItem)(tile_item, id);
// Switch VTable
*(unsigned char **) tile_item = AuxDataTileItem_vtable;
// Configure Item
*(bool *) (tile_item + Item_is_stacked_by_data_property_offset) = true;
*(int32_t *) (tile_item + Item_max_damage_property_offset) = 0;
*(unsigned char **) (tile_item + AuxDataTileItem_icon_tile_property_offset) = Tile_tiles[id + 0x100];
// Return
return ret;
}
// Check Restriction Status
static int is_restricted = 1;
int creative_is_restricted() {
@ -63,6 +101,16 @@ void init_creative() {
// Add Extra Items To Creative Inventory (Only Replace Specific Function Call)
if (feature_has("Expand Creative Inventory", 0)) {
overwrite_call((void *) 0x8e0fc, (void *) Inventory_setupDefault_FillingContainer_addItem_call_injection);
// Use AuxDataTileItem by default instead of TileItem, so tiles in the Creative
// Inventory can have arbitrary auxiliary values.
{
// Fix Size
unsigned char size_patch[4] = {AUX_DATA_TILE_ITEM_SIZE, 0x00, 0xa0, 0xe3}; // "mov r0, #AUX_DATA_TILE_ITEM_SIZE"
patch((void *) 0xc6f64, size_patch);
// Hook Constructor
overwrite_call((void *) 0xc6f74, (void *) Tile_initTiles_TileItem_injection);
}
}
// Remove Creative Restrictions (Opening Chests, Crafting, Etc)
@ -95,6 +143,8 @@ void init_creative() {
// Maximize Creative Inventory Stack Size
unsigned char maximize_stack_patch[4] = {0xff, 0xc0, 0xa0, 0xe3}; // "mov r12, 0xff"
patch((void *) 0x8e104, maximize_stack_patch);
// Allow Nether Reactor
patch((void *) 0xc0290, nop_patch);
// Disable Other Restrictions
is_restricted = 0;
}

View File

@ -6,7 +6,9 @@
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <SDL/SDL.h>
#include <media-layer/core.h>
#include "../init/init.h"
#include "../feature/feature.h"
@ -245,6 +247,11 @@ void init_misc() {
overwrite_calls((void *) GameRenderer_render, (void *) GameRenderer_render_injection);
}
// Disable V-Sync
if (feature_has("Disable V-Sync", 0)) {
media_disable_vsync();
}
// Init C++ And Logging
_init_misc_cpp();
_init_misc_logging();

View File

@ -10,11 +10,6 @@
#include "../home/home.h"
// Check If String Starts With Prefix
static int starts_with(const char *s, const char *t) {
return strncmp(s, t, strlen(t)) == 0;
}
// Get Override Path For File (If It Exists)
char *override_get_path(const char *filename) {
// Get MCPI Home Path

View File

@ -23,7 +23,8 @@ const version = fs.readFileSync('VERSION', 'utf8').trim();
// Packages/Dependencies
const packages = [
'libc6',
'libstdc++6'
'libstdc++6',
'patchelf'
];
if (mode === 'client') {
// GLFW's Dependencies Aren't Included As They Should Be Provided By The Host System

View File

@ -37,7 +37,8 @@ queue_pkg \
queue_pkg \
libfreeimage3 libfreeimage-dev \
libopenal-dev \
qemu-user
qemu-user \
patchelf
# GLFW Dependencies
queue_pkg \

View File

@ -43,6 +43,7 @@ static unsigned char **Tile_netherReactor = (unsigned char **) 0x181dd0; // Tile
static unsigned char **Tile_info_updateGame1 = (unsigned char **) 0x181c68; // Tile
static unsigned char **Tile_info_updateGame2 = (unsigned char **) 0x181c6c; // Tile
static unsigned char **Tile_bedrock = (unsigned char **) 0x181cc4; // Tile
static unsigned char **Tile_tallgrass = (unsigned char **) 0x181d0c; // Tile
static unsigned char **Tile_leaves = (unsigned char **) 0x18120c; // Tile
static unsigned char **Tile_leaves_carried = (unsigned char **) 0x181dd8; // Tile
@ -76,6 +77,8 @@ struct RakNet_SystemAddress {
// Tile
static unsigned char **Tile_tiles = (unsigned char **) 0x180e08;
typedef void (*Tile_initTiles_t)();
static Tile_initTiles_t Tile_initTiles = (Tile_initTiles_t) 0xc358c;
@ -251,6 +254,25 @@ typedef int32_t (*MouseBuildInput_tickBuild_t)(unsigned char *mouse_build_input,
static MouseBuildInput_tickBuild_t MouseBuildInput_tickBuild = (MouseBuildInput_tickBuild_t) 0x17c98;
static void *MouseBuildInput_tickBuild_vtable_addr = (void *) 0x102564;
// Item
static uint32_t Item_is_stacked_by_data_property_offset = 0x19; // unsigned char / bool
static uint32_t Item_category_property_offset = 0x10; // int32_t
static uint32_t Item_max_damage_property_offset = 0x8; // int32_t
// TileItem
typedef unsigned char *(*TileItem_t)(unsigned char *tile_item, int32_t id);
static TileItem_t TileItem = (TileItem_t) 0xce3a4;
// AuxDataTileItem
#define AUX_DATA_TILE_ITEM_SIZE 0x2c
static unsigned char *AuxDataTileItem_vtable = (unsigned char *) 0x114a58;
static uint32_t AuxDataTileItem_icon_tile_property_offset = 0x28; // Tile *
// ItemInstance
typedef struct {