This commit is contained in:
TheBrokenRail 2022-03-14 19:09:25 -04:00
parent bdeb45eed2
commit 03312f44b6
31 changed files with 353 additions and 271 deletions

View File

@ -1 +1 @@
2.3.0
2.3.1

View File

@ -1,5 +1,9 @@
# Changelog
**2.3.1**
* Internal Refactor Of ``libreborn``
* Remove Use Of ``/bin/sh``
**2.3.0**
* Switch To AppImage For Packaging
* Prevent OpenAL From Crashing When Out Of Memory

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -8,7 +8,7 @@ if(BUILD_NATIVE_COMPONENTS)
else()
target_sources(launcher PRIVATE src/client/launcher.cpp)
endif()
target_link_libraries(launcher reborn-headers)
target_link_libraries(launcher reborn-util)
# Install
install(TARGETS launcher DESTINATION "${MCPI_INSTALL_DIR}")
install_symlink("../${MCPI_INSTALL_DIR}/launcher" "bin/${MCPI_VARIANT_NAME}")

View File

@ -313,7 +313,7 @@ void bootstrap(int argc, char *argv[]) {
// Arguments
int argv_start = 2; // argv = &new_args[argv_start]
char *new_args[argv_start /* 2 Potential Prefix Arguments (QEMU And Linker) */ + argc + 1 /* NULL-Terminator */]; //
const char *new_args[argv_start /* 2 Potential Prefix Arguments (QEMU And Linker) */ + argc + 1 /* NULL-Terminator */]; //
// Copy Existing Arguments
for (int i = 1; i < argc; i++) {
@ -344,6 +344,6 @@ void bootstrap(int argc, char *argv[]) {
#endif
// Run
char **new_argv = &new_args[argv_start];
safe_execvpe(new_argv[0], new_argv, environ);
const char **new_argv = &new_args[argv_start];
safe_execvpe(new_argv, (const char *const *) environ);
}

View File

@ -37,49 +37,8 @@ static void load_available_feature_flags(std::function<void(std::string)> callba
}
}
// Run Command And Get Output
static char *run_command(char *command[], int *return_code) {
// Store Output
int output_pipe[2];
safe_pipe2(output_pipe, 0);
// Run
pid_t ret = fork();
if (ret == -1) {
ERR("Unable To Run Command: %s", strerror(errno));
} else if (ret == 0) {
// Child Process
// Pipe stdout
dup2(output_pipe[1], STDOUT_FILENO);
close(output_pipe[0]);
close(output_pipe[1]);
// Run
safe_execvpe(command[0], command, environ);
} else {
// Parent Process
// 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);
}
close(output_pipe[0]);
// Get Return Code
int status;
waitpid(ret, &status, 0);
*return_code = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
// Return
return output;
}
}
// Run Command And Set Environmental Variable
static void run_command_and_set_env(const char *env_name, char *command[]) {
static void run_command_and_set_env(const char *env_name, const char *command[]) {
// Only Run If Environmental Variable Is NULL
if (getenv(env_name) == NULL) {
// Run
@ -93,6 +52,8 @@ static void run_command_and_set_env(const char *env_name, char *command[]) {
}
// Set
set_and_print_env(env_name, output);
// Free
free(output);
}
// Check Return Code
if (return_code != 0) {
@ -107,7 +68,7 @@ static void run_zenity_and_set_env(const char *env_name, std::vector<std::string
std::vector<std::string> full_command;
full_command.push_back("zenity");
full_command.push_back("--class");
full_command.push_back("Minecraft: Pi Edition: Reborn");
full_command.push_back(GUI_TITLE);
full_command.insert(full_command.end(), command.begin(), command.end());
// Convert To C Array
const char *full_command_array[full_command.size() + 1];
@ -116,7 +77,7 @@ static void run_zenity_and_set_env(const char *env_name, std::vector<std::string
}
full_command_array[full_command.size()] = NULL;
// Run
run_command_and_set_env(env_name, (char **) full_command_array);
run_command_and_set_env(env_name, full_command_array);
}
// Launch

View File

@ -3,52 +3,55 @@
#include <cstring>
#include <cstdio>
#include <sstream>
#include <libreborn/libreborn.h>
#include "ldconfig.h"
char *get_full_library_search_path() {
std::string output;
std::string processed_output;
// Run
FILE *file = popen("/sbin/ldconfig -NXv 2> /dev/null", "r");
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) {
char *line = NULL;
size_t length = 0;
if (getline(&line, &length, file) != -1) {
// Convert to C++ String
std::string str(line);
std::string line;
if (std::getline(output_stream, line)) {
// Remove Newline
if (str.size() > 0 && str[str.size() - 1] == '\n') {
str.pop_back();
if (line.size() > 0 && line[line.size() - 1] == '\n') {
line.pop_back();
}
// Interpret
if (str.size() >= 2 && str[0] != '\t' && str[str.size() - 1] == ':') {
if (line.size() >= 2 && line[0] != '\t' && line[line.size() - 1] == ':') {
// Blacklist RPI Legacy GL Drivers
#define RPI_LEGACY_GL_PATH "/opt/vc"
if (str.rfind(RPI_LEGACY_GL_PATH ":", 0) != 0 && str.rfind(RPI_LEGACY_GL_PATH "/", 0) != 0) {
output.append(str);
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(line);
}
// Free Output
free(output);
// Remove Colon
if (output.size() > 0 && output[output.size() - 1] == ':') {
output.pop_back();
}
// Close Process
int ret = pclose(file);
if (ret == -1) {
ERR("ldconfig Failed: %s", strerror(errno));
} else if (ret != 0) {
ERR("ldconfig Failed: Exit Code: %i", ret);
if (processed_output.size() > 0 && processed_output[processed_output.size() - 1] == ':') {
processed_output.pop_back();
}
// Return
char *output_str = strdup(output.c_str());
char *output_str = strdup(processed_output.c_str());
ALLOC_CHECK(output_str);
return output_str;
}

View File

@ -1,12 +1,12 @@
project(libreborn)
add_library(reborn-headers INTERFACE)
target_include_directories(reborn-headers INTERFACE include)
add_library(reborn-util STATIC src/util/elf.c src/util/exec.c src/util/string.c src/util/util.c)
target_include_directories(reborn-util PUBLIC include)
if(BUILD_ARM_COMPONENTS)
add_library(reborn SHARED src/patch.c)
target_link_libraries(reborn dl reborn-headers)
target_compile_definitions(reborn PUBLIC -DREBORN_HAS_COMPILED_CODE)
add_library(reborn-patch SHARED src/patch/patch.c)
target_link_libraries(reborn-patch dl reborn-util)
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
# Install
install(TARGETS reborn DESTINATION "${MCPI_LIB_DIR}")
install(TARGETS reborn-patch DESTINATION "${MCPI_LIB_DIR}")
endif()

View File

@ -0,0 +1,3 @@
#pragma once
#define GUI_TITLE "Minecraft: Pi Edition: Reborn"

View File

@ -9,55 +9,14 @@
#include "log.h"
#include "exec.h"
#ifdef __cplusplus
extern "C" {
#endif
// Find And Iterate Over All .text Sections In Current Binary
typedef void (*text_section_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data);
static inline void iterate_text_sections(text_section_callback_t callback, void *data) {
// Load Main Binary
FILE *file_obj = fopen(getenv("MCPI_EXECUTABLE_PATH"), "rb");
void iterate_text_sections(text_section_callback_t callback, void *data);
// Verify Binary
if (!file_obj) {
ERR("%s", "Unable To Open Current Binary");
}
// Get File Size
fseek(file_obj, 0L, SEEK_END);
long int file_size = ftell(file_obj);
fseek(file_obj, 0L, SEEK_SET);
// Map File To Pointer
unsigned char *file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
// Parse ELF
ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_map;
ElfW(Shdr) *elf_section_headers = (ElfW(Shdr) *) (file_map + elf_header->e_shoff);
int elf_section_header_count = elf_header->e_shnum;
// Locate Section Names
ElfW(Shdr) elf_shstrtab = elf_section_headers[elf_header->e_shstrndx];
unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset;
// Track .text Sections
int text_sections = 0;
// Iterate Sections
for (int i = 0; i < elf_section_header_count; ++i) {
ElfW(Shdr) header = elf_section_headers[i];
char *name = (char *) (elf_shstrtab_p + header.sh_name);
// Check Section Type
if (strcmp(name, ".text") == 0) {
// .text Section
(*callback)(header.sh_addr, header.sh_size, data);
text_sections++;
}
}
// Ensure At Least .text Section Was Scanned
if (text_sections < 1) {
ERR("%s", "Unable To Find .text Sectons");
}
// Unmap And Close File
munmap(file_map, file_size);
fclose(file_obj);
#ifdef __cplusplus
}
#endif

View File

@ -4,60 +4,34 @@
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include "log.h"
#include "string.h"
#include "util.h"
#ifdef __cplusplus
extern "C" {
#endif
// Safe execvpe()
__attribute__((noreturn)) static inline void safe_execvpe(const char *pathname, char *argv[], char *const envp[]) {
argv[0] = (char *) pathname;
int ret = execvpe(pathname, argv, envp);
if (ret == -1) {
ERR("Unable To Execute Program: %s: %s", pathname, strerror(errno));
} else {
ERR("%s", "Unknown execvpe() Error");
}
}
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]);
// Chop Off Last Component
static inline void chop_last_component(char **str) {
size_t length = strlen(*str);
for (size_t i = 0; i < length; i++) {
size_t j = length - i - 1;
if ((*str)[j] == '/') {
(*str)[j] = '\0';
break;
}
}
}
void chop_last_component(char **str);
// Get Binary Directory (Remember To Free)
static inline char *get_binary_directory() {
// Get Path To Current Executable
char *exe = realpath("/proc/self/exe", NULL);
ALLOC_CHECK(exe);
// Chop Off Last Component
chop_last_component(&exe);
// Return
return exe;
}
char *get_binary_directory();
// Safe execvpe() Relative To Binary
__attribute__((noreturn)) static inline void safe_execvpe_relative_to_binary(const char *pathname, char *argv[], char *const envp[]) {
// Get Binary Directory
char *binary_directory = get_binary_directory();
// Create Full Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/%s", binary_directory, pathname);
// Free Binary Directory
free(binary_directory);
// Run
safe_execvpe(full_path, argv, envp);
}
__attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const argv[], const char *const envp[]);
// Get MCPI Directory
static inline char *get_mcpi_directory() {
return getenv("MCPI_DIRECTORY");
char *get_mcpi_directory();
// Run Command And Get Output
char *run_command(const char *const command[], int *return_code);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,6 @@
#pragma once
#include "config.h"
#include "log.h"
#include "util.h"
#include "string.h"

View File

@ -6,7 +6,7 @@ extern "C" {
// Patching Functions
#ifdef REBORN_HAS_COMPILED_CODE
#ifdef REBORN_HAS_PATCH_CODE
void _overwrite_call(const char *file, int line, void *start, void *target);
#define overwrite_call(start, target) _overwrite_call(__FILE__, __LINE__, start, target);
@ -23,7 +23,7 @@ void _patch(const char *file, int line, void *start, unsigned char patch[4]);
void _patch_address(const char *file, int line, void *start, void *target);
#define patch_address(start, target) _patch_address(__FILE__, __LINE__, start, target);
#endif // #ifdef REBORN_HAS_COMPILED_CODE
#endif
#ifdef __cplusplus
}

View File

@ -26,26 +26,13 @@
} \
}
#ifdef __cplusplus
extern "C" {
#endif
// Sanitize String
#define MINIMUM_SAFE_CHARACTER 32
#define MAXIMUM_SAFE_CHARACTER 126
static inline void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
// Store Message Length
int length = strlen(*str);
// Truncate Message
if (max_length != -1 && length > max_length) {
(*str)[max_length] = '\0';
length = max_length;
}
// Loop Through Message
for (int i = 0; i < length; i++) {
if (allow_newlines && ((*str)[i] == '\n' || (*str)[i] == '\r')) {
continue;
}
unsigned char c = (unsigned char) (*str)[i];
if (c < MINIMUM_SAFE_CHARACTER || c > MAXIMUM_SAFE_CHARACTER) {
// Replace Illegal Character
(*str)[i] = '?';
}
}
void sanitize_string(char **str, int max_length, unsigned int allow_newlines);
#ifdef __cplusplus
}
#endif

View File

@ -43,9 +43,13 @@
} \
}
#ifdef __cplusplus
extern "C" {
#endif
// Safe Version Of pipe()
static inline void safe_pipe2(int pipefd[2], int flags) {
if (pipe2(pipefd, flags) != 0) {
ERR("Unable To Create Pipe: %s", strerror(errno));
}
void safe_pipe2(int pipefd[2], int flags);
#ifdef __cplusplus
}
#endif

View File

@ -11,7 +11,7 @@
#ifndef __arm__
#error "Patching Code Is ARM Only"
#endif // #ifndef __arm__
#endif
// BL Instruction Magic Number
#define BL_INSTRUCTION 0xeb

53
libreborn/src/util/elf.c Normal file
View File

@ -0,0 +1,53 @@
#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) {
// Load Main Binary
FILE *file_obj = fopen(getenv("MCPI_EXECUTABLE_PATH"), "rb");
// Verify Binary
if (!file_obj) {
ERR("%s", "Unable To Open Current Binary");
}
// Get File Size
fseek(file_obj, 0L, SEEK_END);
long int file_size = ftell(file_obj);
fseek(file_obj, 0L, SEEK_SET);
// Map File To Pointer
unsigned char *file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
// Parse ELF
ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_map;
ElfW(Shdr) *elf_section_headers = (ElfW(Shdr) *) (file_map + elf_header->e_shoff);
int elf_section_header_count = elf_header->e_shnum;
// Locate Section Names
ElfW(Shdr) elf_shstrtab = elf_section_headers[elf_header->e_shstrndx];
unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset;
// Track .text Sections
int text_sections = 0;
// Iterate Sections
for (int i = 0; i < elf_section_header_count; ++i) {
ElfW(Shdr) header = elf_section_headers[i];
char *name = (char *) (elf_shstrtab_p + header.sh_name);
// Check Section Type
if (strcmp(name, ".text") == 0) {
// .text Section
(*callback)(header.sh_addr, header.sh_size, data);
text_sections++;
}
}
// Ensure At Least .text Section Was Scanned
if (text_sections < 1) {
ERR("%s", "Unable To Find .text Sectons");
}
// Unmap And Close File
munmap(file_map, file_size);
fclose(file_obj);
}

113
libreborn/src/util/exec.c Normal file
View File

@ -0,0 +1,113 @@
#include <libreborn/exec.h>
// Safe execvpe()
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]) {
int ret = execvpe(argv[0], (char *const *) argv, (char *const *) envp);
if (ret == -1) {
ERR("Unable To Execute Program: %s: %s", argv[0], strerror(errno));
} else {
IMPOSSIBLE();
}
}
// Chop Off Last Component
void chop_last_component(char **str) {
size_t length = strlen(*str);
for (size_t i = 0; i < length; i++) {
size_t j = length - i - 1;
if ((*str)[j] == '/') {
(*str)[j] = '\0';
break;
}
}
}
// Get Binary Directory (Remember To Free)
char *get_binary_directory() {
// Get Path To Current Executable
char *exe = realpath("/proc/self/exe", NULL);
ALLOC_CHECK(exe);
// Chop Off Last Component
chop_last_component(&exe);
// Return
return exe;
}
// Safe execvpe() Relative To Binary
__attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const argv[], const char *const envp[]) {
// Get Binary Directory
char *binary_directory = get_binary_directory();
// Create Full Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/%s", binary_directory, argv[0]);
// Free Binary Directory
free(binary_directory);
// Build New argv
int argc;
for (argc = 0; argv[argc] != NULL; argc++);
const char *new_argv[argc + 1];
for (int i = 1; i < argc; i++) {
new_argv[i] = argv[i];
}
new_argv[0] = full_path;
new_argv[argc] = NULL;
// Run
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
int output_pipe[2];
safe_pipe2(output_pipe, 0);
// Run
pid_t ret = fork();
if (ret == -1) {
ERR("Unable To Run Command: %s", strerror(errno));
} else if (ret == 0) {
// Child Process
// Pipe stdout
dup2(output_pipe[1], STDOUT_FILENO);
close(output_pipe[0]);
close(output_pipe[1]);
// Close stderr (But Not In Debug Mode)
const char *is_debug = getenv("MCPI_DEBUG");
if (is_debug == NULL || strlen(is_debug) < 1) {
int null_fd = open("/dev/null", O_WRONLY);
dup2(null_fd, STDERR_FILENO);
close(null_fd);
}
// Run
safe_execvpe(command, (const char *const *) environ);
} else {
// Parent Process
// 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);
}
close(output_pipe[0]);
// Get Return Code
int status;
waitpid(ret, &status, 0);
*return_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
// Return
return output;
}
}

View File

@ -0,0 +1,25 @@
#include <libreborn/string.h>
// Sanitize String
#define MINIMUM_SAFE_CHARACTER 32
#define MAXIMUM_SAFE_CHARACTER 126
void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
// Store Message Length
int length = strlen(*str);
// Truncate Message
if (max_length != -1 && length > max_length) {
(*str)[max_length] = '\0';
length = max_length;
}
// Loop Through Message
for (int i = 0; i < length; i++) {
if (allow_newlines && ((*str)[i] == '\n' || (*str)[i] == '\r')) {
continue;
}
unsigned char c = (unsigned char) (*str)[i];
if (c < MINIMUM_SAFE_CHARACTER || c > MAXIMUM_SAFE_CHARACTER) {
// Replace Illegal Character
(*str)[i] = '?';
}
}
}

View File

@ -0,0 +1,8 @@
#include <libreborn/util.h>
// Safe Version Of pipe()
void safe_pipe2(int pipefd[2], int flags) {
if (pipe2(pipefd, flags) != 0) {
ERR("Unable To Create Pipe: %s", strerror(errno));
}
}

View File

@ -20,7 +20,7 @@ endif()
# Configure Media Layer Core If Built
if(TARGET media-layer-core)
# Link
target_link_libraries(media-layer-core media-layer-headers reborn-headers pthread dl)
target_link_libraries(media-layer-core media-layer-headers reborn-util pthread dl)
if(NOT MCPI_HEADLESS_MODE)
# Find FreeImage
find_library(FREEIMAGE_LIBRARY NAMES freeimage libfreeimage.so.3 REQUIRED)

View File

@ -6,7 +6,7 @@
#ifndef MCPI_HEADLESS_MODE
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
#include <libreborn/libreborn.h>
#include <media-layer/core.h>
@ -14,7 +14,7 @@
#ifndef MCPI_HEADLESS_MODE
#include "audio/engine.h"
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
// Allow Disabling Interaction
static void update_cursor();
@ -222,7 +222,7 @@ static void glfw_scroll(__attribute__((unused)) GLFWwindow *window, __attribute_
}
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
// Track Media Layer State
static int is_running = 0;
@ -235,7 +235,7 @@ void media_set_raw_mouse_motion_enabled(int enabled) {
if (is_running) {
glfwSetInputMode(glfw_window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE);
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
if (!raw_mouse_motion_enabled) {
WARN("%s", "Raw mouse motion has been DISABLED, this IS NOT recommended, and should only ever be used on systems that don't support or have broken raw mouse motion.");
}
@ -249,7 +249,7 @@ void media_disable_vsync() {
if (is_running) {
glfwSwapInterval(0);
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
}
// Init Media Layer
@ -289,9 +289,9 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
// Init OpenAL
_media_audio_init();
#else // #ifndef MCPI_HEADLESS_MODE
#else
(void) title; // Mark As Used
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
// Set State
is_running = 1;
@ -307,7 +307,7 @@ void media_swap_buffers() {
#ifndef MCPI_HEADLESS_MODE
// Don't Swap Buffers In A Context-Less Window
glfwSwapBuffers(glfw_window);
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
}
// Fullscreen Not Needed In Headless Mode
@ -340,10 +340,10 @@ void media_toggle_fullscreen() {
}
is_fullscreen = !is_fullscreen;
}
#else // #ifndef MCPI_HEADLESS_MODE
#else
void media_toggle_fullscreen() {
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
// Intercept SDL Events
void _media_handle_SDL_PollEvent() {
@ -359,7 +359,7 @@ void _media_handle_SDL_PollEvent() {
SDL_PushEvent(&event);
glfwSetWindowShouldClose(glfw_window, GLFW_FALSE);
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
}
// Cleanup Media Layer
@ -376,7 +376,7 @@ void media_cleanup() {
// Cleanup OpenAL
_media_audio_cleanup();
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
// Update State
is_running = 0;
@ -437,7 +437,7 @@ static void update_cursor() {
}
}
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
}
// Fix SDL Cursor Visibility/Grabbing
@ -483,7 +483,7 @@ void media_get_framebuffer_size(int *width, int *height) {
glfwGetFramebufferSize(glfw_window, width, height);
return;
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif
*width = DEFAULT_WIDTH;
*height = DEFAULT_HEIGHT;
}

View File

@ -122,8 +122,8 @@ __attribute__((constructor)) static void init() {
FreeImage_Initialise(0);
}
#else // #ifndef MCPI_HEADLESS_MODE
#else
void media_take_screenshot() {
// NOP
}
#endif // #ifndef MCPI_HEADLESS_MODE
#endif

View File

@ -9,7 +9,7 @@ if(BUILD_NATIVE_COMPONENTS)
# Build Media Layer Proxy Client
add_executable(media-layer-proxy-client src/client/client.cpp ${MEDIA_LAYER_PROXY_SRC})
target_link_libraries(media-layer-proxy-client media-layer-headers reborn-headers ${MEDIA_LAYER_PROXY_LIBS})
target_link_libraries(media-layer-proxy-client media-layer-headers reborn-util ${MEDIA_LAYER_PROXY_LIBS})
target_compile_definitions(media-layer-proxy-client PRIVATE -DMEDIA_LAYER_PROXY_CLIENT)
# Install
install(TARGETS media-layer-proxy-client DESTINATION "${MCPI_BIN_DIR}")
@ -20,7 +20,7 @@ if(BUILD_ARM_COMPONENTS)
# Build Media Layer Proxy Server
add_library(media-layer-core SHARED src/server/server.cpp ${MEDIA_LAYER_PROXY_SRC})
target_link_libraries(media-layer-core media-layer-headers reborn-headers)
target_link_libraries(media-layer-core media-layer-headers reborn-util)
target_compile_definitions(media-layer-core PRIVATE -DMEDIA_LAYER_PROXY_SERVER)
# Symlink GLESv1_CM To Media Layer Proxy Server
install_symlink("libmedia-layer-core.so" "${MCPI_LIB_DIR}/libGLESv1_CM.so.1")

View File

@ -77,10 +77,10 @@ static void start_media_layer_proxy_client(int read, int write) {
safe_asprintf(&read_str, "%i", read);
char *write_str = NULL;
safe_asprintf(&write_str, "%i", write);
char *argv[] = {NULL /* Updated By safe_execvpe() */, read_str, write_str, NULL};
const char *argv[] = {"media-layer-proxy-client", read_str, write_str, NULL};
// Run
safe_execvpe("media-layer-proxy-client", argv, environ);
safe_execvpe(argv, (const char *const *) environ);
} else {
// Parent Process
_client_pid = ret;

View File

@ -14,11 +14,11 @@ if(BUILD_ARM_COMPONENTS)
# Stub EGL
add_library(EGL SHARED src/EGL.c)
target_link_libraries(EGL reborn-headers media-layer-headers)
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-headers media-layer-headers)
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)

View File

@ -8,80 +8,80 @@ 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)
target_link_libraries(compat reborn media-layer-core)
target_link_libraries(compat reborn-patch media-layer-core)
add_library(readdir SHARED src/readdir/readdir.c)
add_library(feature SHARED src/feature/feature.c)
target_link_libraries(feature reborn)
target_link_libraries(feature reborn-patch)
add_library(version SHARED src/version/version.cpp)
target_link_libraries(version reborn symbols)
target_link_libraries(version reborn-patch symbols)
add_library(chat SHARED src/chat/chat.cpp src/chat/ui.c)
target_link_libraries(chat reborn symbols feature pthread)
target_link_libraries(chat reborn-patch symbols feature pthread)
if(MCPI_SERVER_MODE)
add_library(server SHARED src/server/server.cpp src/server/server_properties.cpp)
target_link_libraries(server reborn symbols feature home misc compat dl media-layer-core pthread)
target_link_libraries(server reborn-patch symbols feature home misc compat dl media-layer-core pthread)
else()
target_link_libraries(compat input sign chat home dl)
target_link_libraries(chat input)
add_library(multiplayer SHARED src/multiplayer/multiplayer.cpp)
target_link_libraries(multiplayer reborn symbols home feature)
target_link_libraries(multiplayer reborn-patch symbols home feature)
add_library(sound SHARED src/sound/sound.cpp src/sound/repository.cpp)
target_link_libraries(sound reborn symbols feature override media-layer-core)
target_link_libraries(sound reborn-patch symbols feature override media-layer-core)
add_library(camera SHARED src/camera/camera.cpp)
target_link_libraries(camera reborn symbols media-layer-core feature home)
target_link_libraries(camera reborn-patch symbols media-layer-core feature home)
add_library(input SHARED src/input/input.cpp src/input/bow.c src/input/attack.c src/input/toggle.c src/input/misc.c src/input/drop.cpp)
target_link_libraries(input reborn symbols creative feature media-layer-core)
target_link_libraries(input reborn-patch symbols creative feature media-layer-core)
add_library(sign SHARED src/sign/sign.cpp)
target_link_libraries(sign reborn symbols feature input)
target_link_libraries(sign reborn-patch symbols feature input)
add_library(creative SHARED src/creative/creative.cpp)
target_link_libraries(creative reborn symbols feature)
target_link_libraries(creative reborn-patch symbols feature)
add_library(touch SHARED src/touch/touch.c)
target_link_libraries(touch reborn symbols feature)
target_link_libraries(touch reborn-patch symbols feature)
add_library(override SHARED src/override/override.c)
target_link_libraries(override reborn symbols dl home)
target_link_libraries(override reborn-patch symbols dl home)
add_library(textures SHARED src/textures/textures.cpp)
target_link_libraries(textures reborn symbols media-layer-core feature)
target_link_libraries(textures reborn-patch symbols media-layer-core feature)
add_library(atlas SHARED src/atlas/atlas.cpp)
target_link_libraries(atlas reborn symbols feature GLESv1_CM)
target_link_libraries(atlas reborn-patch symbols feature GLESv1_CM)
if(NOT MCPI_HEADLESS_MODE)
add_library(benchmark SHARED src/benchmark/benchmark.cpp)
target_link_libraries(benchmark reborn symbols compat misc media-layer-core)
target_link_libraries(benchmark reborn-patch symbols compat misc media-layer-core)
endif()
endif()
add_library(game-mode SHARED src/game-mode/game-mode.c src/game-mode/game-mode.cpp)
target_link_libraries(game-mode reborn symbols feature)
target_link_libraries(game-mode reborn-patch symbols feature)
add_library(death SHARED src/death/death.cpp)
target_link_libraries(death reborn symbols feature)
target_link_libraries(death reborn-patch symbols feature)
add_library(misc SHARED src/misc/misc.c src/misc/misc.cpp src/misc/logging.cpp)
target_link_libraries(misc reborn symbols feature GLESv1_CM)
target_link_libraries(misc reborn-patch symbols feature GLESv1_CM)
add_library(options SHARED src/options/options.c)
target_link_libraries(options reborn symbols feature)
target_link_libraries(options reborn-patch symbols feature)
add_library(home SHARED src/home/home.c)
target_link_libraries(home reborn symbols)
target_link_libraries(home reborn-patch symbols)
add_library(test SHARED src/test/test.c)
target_link_libraries(test reborn home)
target_link_libraries(test reborn-patch home)
add_library(init SHARED src/init/init.c)
target_link_libraries(init compat game-mode misc death options chat home version test media-layer-core)

View File

@ -11,7 +11,7 @@
#include "../feature/feature.h"
#ifndef MCPI_SERVER_MODE
#include "../input/input.h"
#endif // #ifndef MCPI_SERVER_MODE
#endif
#include "chat.h"
// Store If Chat is Enabled
@ -39,7 +39,7 @@ static void send_api_chat_command(unsigned char *minecraft, char *str) {
send_api_command(minecraft, command);
free(command);
}
#endif // #ifndef MCPI_SERVER_MODE
#endif
// Send Message To Players
static void send_message(unsigned char *server_side_network_handler, char *username, char *message) {
@ -115,7 +115,7 @@ static void send_queued_messages(unsigned char *minecraft) {
// Unlock
pthread_mutex_unlock(&queue_mutex);
}
#endif // #ifndef MCPI_SERVER_MODE
#endif
// Init
void init_chat() {
@ -131,6 +131,6 @@ void init_chat() {
// Send Messages On Input Tick
#ifndef MCPI_SERVER_MODE
input_run_on_tick(send_queued_messages);
#endif // #ifndef MCPI_SERVER_MODE
#endif
}
}

View File

@ -10,27 +10,13 @@
#include "../input/input.h"
// Run Command
static char *run_command(char *command, int *return_code) {
static char *run_command_proper(const char *command[], int *return_code) {
// Prepare Environment
RESET_ENVIRONMENTAL_VARIABLE("LD_LIBRARY_PATH");
RESET_ENVIRONMENTAL_VARIABLE("LD_PRELOAD");
// Start
FILE *out = popen(command, "r");
if (!out) {
ERR("%s", "Failed To Run Command");
}
// Record
char *output = NULL;
int c;
while ((c = fgetc(out)) != EOF) {
string_append(&output, "%c", (char) c);
}
// Return
*return_code = WEXITSTATUS(pclose(out));
return output;
// Run
return run_command(command, return_code);
}
// Count Chat Windows
@ -44,7 +30,8 @@ unsigned int chat_get_counter() {
static void *chat_thread(__attribute__((unused)) void *nop) {
// Open
int return_code;
char *output = run_command("zenity --title 'Chat' --class 'Minecraft: Pi Edition: Reborn' --entry --text 'Enter Chat Message:'", &return_code);
const char *command[] = {"zenity", "--title", "Chat", "--class", GUI_TITLE, "--entry", "--text", "Enter Chat Message:", NULL};
char *output = run_command_proper(command, &return_code);
// Handle Message
if (output != NULL) {
// Check Return Code
@ -87,4 +74,4 @@ void chat_open() {
pthread_create(&thread, NULL, chat_thread, NULL);
}
}
#endif // #ifndef MCPI_SERVER_MODE
#endif

View File

@ -18,7 +18,7 @@
// Custom Title
HOOK(SDL_WM_SetCaption, void, (__attribute__((unused)) const char *title, const char *icon)) {
ensure_SDL_WM_SetCaption();
(*real_SDL_WM_SetCaption)("Minecraft: Pi Edition: Reborn", icon);
(*real_SDL_WM_SetCaption)(GUI_TITLE, icon);
}
// Mouse Cursor Is Always Invisible In Vanilla MCPI
@ -106,7 +106,7 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
return ret;
}
#endif // #ifndef MCPI_SERVER_MODE
#endif
// Exit Handler
static void exit_handler(__attribute__((unused)) int data) {

View File

@ -30,7 +30,7 @@ static int get_render_distance() {
ERR("Invalid Render Distance: %s", distance_str);
}
}
#endif // #ifndef MCPI_SERVER_MODE
#endif
// Get Custom Username
static char *get_username() {
@ -86,9 +86,9 @@ void init_options() {
#ifndef MCPI_SERVER_MODE
render_distance = get_render_distance();
INFO("Setting Render Distance: %i", render_distance);
#else // #ifndef MCPI_SERVER_MODE
#else
render_distance = 3;
#endif // #ifndef MCPI_SERVER_MODE
#endif
// Server Visible
server_visible = !feature_has("Disable Hosting LAN Worlds", 0);
@ -99,7 +99,7 @@ void init_options() {
const char *username = get_username();
#ifndef MCPI_SERVER_MODE
INFO("Setting Username: %s", username);
#endif // #ifndef MCPI_SERVER_MODE
#endif
if (strcmp(*default_username, "StevePi") != 0) {
ERR("%s", "Default Username Is Invalid");
}