194 lines
5.1 KiB
C++
Raw Normal View History

2024-05-12 03:19:01 -04:00
#define _FILE_OFFSET_BITS 64
#include <string>
#include <vector>
#include <libreborn/libreborn.h>
#include "util.h"
#include "bootstrap.h"
#include "patchelf.h"
#define MCPI_BINARY "minecraft-pi"
#define REQUIRED_PAGE_SIZE 4096
// Debug Information
static void run_debug_command(const char *const command[], const char *prefix) {
int status = 0;
char *output = run_command(command, &status, nullptr);
if (output != nullptr) {
// Remove Newline
size_t length = strlen(output);
if (length > 0 && output[length - 1] == '\n') {
output[length - 1] = '\0';
}
// Print
DEBUG("%s: %s", prefix, output);
free(output);
}
if (!is_exit_status_success(status)) {
ERR("Unable To Gather Debug Information");
}
}
static void print_debug_information() {
// System Information
const char *const command[] = {"uname", "-a", nullptr};
run_debug_command(command, "System Information");
// Version
DEBUG("Reborn Version: v%s", MCPI_VERSION);
// Architecture
const char *arch =
2024-05-12 03:19:01 -04:00
#ifdef __x86_64__
"AMD64"
2024-05-12 03:19:01 -04:00
#elif defined(__aarch64__)
"ARM64"
2024-05-12 03:19:01 -04:00
#elif defined(__arm__)
"ARM32"
#else
"Unknown"
2024-05-12 03:19:01 -04:00
#endif
;
2024-05-12 03:19:01 -04:00
DEBUG("Reborn Target Architecture: %s", arch);
}
// Bootstrap
void bootstrap() {
// Debug Information
print_debug_information();
// Check Page Size (Not Needed When Using QEMU)
2024-06-08 18:00:30 -04:00
#ifndef MCPI_RUNTIME_IS_QEMU
2024-05-12 03:19:01 -04:00
long page_size = sysconf(_SC_PAGESIZE);
if (page_size != REQUIRED_PAGE_SIZE) {
ERR("Invalid page size! A page size of %ld bytes is required, but the system size is %ld bytes.", (long) REQUIRED_PAGE_SIZE, page_size);
}
#endif
// Get Binary Directory
const std::string binary_directory = get_binary_directory();
2024-05-12 03:19:01 -04:00
DEBUG("Binary Directory: %s", binary_directory.c_str());
// Copy SDK
2024-06-16 00:04:42 -04:00
if (!reborn_is_server()) {
copy_sdk(binary_directory, true);
}
2024-05-12 03:19:01 -04:00
// Set MCPI_REBORN_ASSETS_PATH
{
std::string assets_path = safe_realpath("/proc/self/exe");
chop_last_component(assets_path);
assets_path += "/data";
set_and_print_env(_MCPI_REBORN_ASSETS_PATH_ENV, assets_path.c_str());
2024-05-12 03:19:01 -04:00
}
// Resolve Binary Path & Set MCPI_DIRECTORY
std::string game_binary;
2024-05-12 03:19:01 -04:00
{
// Log
DEBUG("Resolving File Paths...");
// Resolve Full Binary Path
const std::string full_path = binary_directory + ("/" MCPI_BINARY);
game_binary = safe_realpath(full_path);
2024-05-12 03:19:01 -04:00
}
// Fix MCPI Dependencies
char new_mcpi_exe_path[] = MCPI_PATCHED_DIR "/XXXXXX";
2024-05-20 16:37:55 -04:00
std::string linker;
2024-05-12 03:19:01 -04:00
{
// Log
DEBUG("Patching ELF Dependencies...");
// Find Linker
2024-05-20 16:37:55 -04:00
linker = "/lib/ld-linux-armhf.so.3";
2024-05-12 03:19:01 -04:00
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
// Use ARM Sysroot Linker
2024-05-20 16:37:55 -04:00
linker = binary_directory + "/sysroot" + linker;
2024-05-12 03:19:01 -04:00
#endif
// Patch
patch_mcpi_elf_dependencies(game_binary.c_str(), new_mcpi_exe_path);
2024-05-12 03:19:01 -04:00
// Verify
if (!starts_with(new_mcpi_exe_path, MCPI_PATCHED_DIR)) {
IMPOSSIBLE();
}
}
// Set MCPI_VANILLA_ASSETS_PATH
{
std::string assets_path = game_binary;
chop_last_component(assets_path);
assets_path += "/data";
set_and_print_env(_MCPI_VANILLA_ASSETS_PATH_ENV, assets_path.c_str());
2024-05-12 03:19:01 -04:00
}
// Configure Library Search Path
2024-05-20 16:37:55 -04:00
std::string mcpi_ld_path = "";
2024-05-12 03:19:01 -04:00
{
// Log
DEBUG("Setting Linker Search Paths...");
// Library Search Path For ARM Components
{
// Add ARM Library Directory
mcpi_ld_path += binary_directory + "/lib/arm:";
// Add ARM Sysroot Libraries (Ensure Priority) (Ignore On Actual ARM System)
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
mcpi_ld_path += binary_directory + "/sysroot/lib:";
mcpi_ld_path += binary_directory + "/sysroot/lib/arm-linux-gnueabihf:";
mcpi_ld_path += binary_directory + "/sysroot/usr/lib:";
mcpi_ld_path += binary_directory + "/sysroot/usr/lib/arm-linux-gnueabihf:";
#endif
}
}
// Configure Preloaded Objects
2024-05-20 16:37:55 -04:00
std::string mcpi_ld_preload;
2024-05-12 03:19:01 -04:00
{
// Log
DEBUG("Locating Mods...");
// ARM Components
2024-05-20 16:37:55 -04:00
mcpi_ld_preload = bootstrap_mods(binary_directory);
2024-05-12 03:19:01 -04:00
}
// Start Game
INFO("Starting Game...");
// Arguments
std::vector<std::string> args;
2024-06-08 16:30:39 -04:00
// Use Extra If Needed
#ifdef MCPI_BUILD_RUNTIME
args.push_back("runtime");
2024-06-04 18:29:13 -04:00
#endif
// Fix QEMU Bug
2024-06-08 16:30:39 -04:00
#ifdef MCPI_RUNTIME_IS_QEMU
2024-05-20 16:37:55 -04:00
args.push_back("-B");
2024-06-04 18:29:13 -04:00
args.push_back("0x40000"); // Arbitrary Value (Aligns To 4k And 16k Page Sizes)
2024-05-12 03:19:01 -04:00
#endif
2024-05-20 16:37:55 -04:00
// Setup Linker
args.push_back(linker);
args.push_back("--library-path");
args.push_back(mcpi_ld_path);
args.push_back("--preload");
args.push_back(mcpi_ld_preload);
2024-05-12 03:19:01 -04:00
// Specify MCPI Binary
args.push_back(new_mcpi_exe_path);
// Run
const char *new_argv[args.size() + 1];
for (std::vector<std::string>::size_type i = 0; i < args.size(); i++) {
new_argv[i] = args[i].c_str();
}
new_argv[args.size()] = nullptr;
safe_execvpe(new_argv, environ);
}