Initial Commit
This commit is contained in:
commit
9cba611982
4
.dockerignore
Normal file
4
.dockerignore
Normal file
@ -0,0 +1,4 @@
|
||||
.git
|
||||
.gitignore
|
||||
Dockerfile
|
||||
README.md
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/minecraft-pi
|
||||
/libpng
|
||||
/core/build
|
||||
/mods/build
|
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@ -0,0 +1,25 @@
|
||||
FROM arm64v8/debian:bullseye
|
||||
|
||||
RUN dpkg --add-architecture armhf
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get upgrade -y
|
||||
|
||||
RUN apt-get install -y libglvnd-dev:armhf libsdl1.2-dev:armhf libx11-dev:armhf build-essential zlib1g-dev:armhf git cmake curl gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf gdb
|
||||
|
||||
RUN ln -s /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2 /usr/lib/libGLESv2.so
|
||||
RUN ln -s /usr/lib/arm-linux-gnueabihf/libEGL.so.1 /usr/lib/libEGL.so
|
||||
|
||||
ADD . /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN ./scripts/download-minecraft-pi.sh
|
||||
|
||||
RUN ./scripts/build-mods.sh
|
||||
|
||||
RUN ./scripts/build-libpng12.sh
|
||||
|
||||
WORKDIR /app/minecraft-pi
|
||||
|
||||
ENTRYPOINT ./launcher
|
23
README.md
Normal file
23
README.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Minecraft: Pi Edition For Docker
|
||||
|
||||
## Dependencies
|
||||
```sh
|
||||
# Required For Hardware Acceleration
|
||||
sudo apt install virgl-server
|
||||
|
||||
# Required For ARM Support
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
```
|
||||
|
||||
## Tutorial
|
||||
```sh
|
||||
virgl_test_server &
|
||||
PID="$!"
|
||||
|
||||
sudo docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /tmp/.virgl_test:/tmp/.virgl_test -v ~/.minecraft-pi:/root/.minecraft -e DISPLAY=unix${DISPLAY} thebrokenrail/minecraft-pi
|
||||
|
||||
kill "${PID}"
|
||||
```
|
||||
|
||||
## Tweaks
|
||||
The included version of Minecraft: Pi Ediiton is slightly modified so it uses the old touchscreen UI.
|
5
build.sh
Executable file
5
build.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
sudo docker build --tag thebrokenrail/minecraft-pi:latest .
|
5
cmake/toolchain.cmake
Normal file
5
cmake/toolchain.cmake
Normal file
@ -0,0 +1,5 @@
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
14
core/CMakeLists.txt
Normal file
14
core/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
|
||||
project(core)
|
||||
|
||||
add_compile_options(-Wall -Wextra -Werror)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
add_library(core SHARED src/core.c)
|
||||
target_link_libraries(core dl)
|
||||
|
||||
add_library(bcm_host SHARED src/bcm_host.c)
|
||||
|
||||
add_executable(launcher src/launcher.c)
|
37
core/include/libcore/libcore.h
Normal file
37
core/include/libcore/libcore.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef LIBLOADER_H
|
||||
|
||||
#define LIBLOADER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define HOOK(name, return_type, args) \
|
||||
typedef return_type (*name##_t)args; \
|
||||
static name##_t real_##name = NULL; \
|
||||
\
|
||||
__attribute__((__unused__)) static void ensure_##name() { \
|
||||
if (!real_##name) { \
|
||||
dlerror(); \
|
||||
real_##name = (name##_t) dlsym(RTLD_NEXT, #name); \
|
||||
if (!real_##name) { \
|
||||
fprintf(stderr, "Error Resolving Symbol: "#name": %s\n", dlerror()); \
|
||||
exit(1); \
|
||||
} \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
__attribute__((__used__)) return_type name args
|
||||
|
||||
void overwrite(void *start, void *target);
|
||||
void patch(void *start, unsigned char patch[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
39
core/src/bcm_host.c
Normal file
39
core/src/bcm_host.c
Normal file
@ -0,0 +1,39 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
unsigned bcm_host_get_peripheral_address(void) {
|
||||
return 0x20000000;
|
||||
}
|
||||
|
||||
unsigned bcm_host_get_peripheral_size(void) {
|
||||
return 0x01000000;
|
||||
}
|
||||
|
||||
unsigned bcm_host_get_sdram_address(void) {
|
||||
return 0x40000000;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
44
core/src/core.c
Normal file
44
core/src/core.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libcore/libcore.h>
|
||||
|
||||
#define PREPARE_PATCH(start) \
|
||||
size_t page_size = sysconf(_SC_PAGESIZE); \
|
||||
uintptr_t end = ((uintptr_t) start) + 1; \
|
||||
uintptr_t page_start = ((uintptr_t) start) & -page_size; \
|
||||
mprotect((void *) page_start, end - page_start, PROT_READ | PROT_WRITE); \
|
||||
\
|
||||
unsigned char *data = (unsigned char *) start; \
|
||||
int thumb = ((size_t) start) & 1; \
|
||||
if (thumb) { \
|
||||
data--; \
|
||||
} \
|
||||
fprintf(stderr, "Patching - original: %i %i %i %i %i\n", data[0], data[1], data[2], data[3], data[4]);
|
||||
|
||||
#define END_PATCH() \
|
||||
fprintf(stderr, "Patching - result: %i %i %i %i %i\n", data[0], data[1], data[2], data[3], data[4]); \
|
||||
\
|
||||
mprotect((void *) page_start, end - page_start, PROT_READ | PROT_EXEC);
|
||||
|
||||
void overwrite(void *start, void *target) {
|
||||
PREPARE_PATCH(start);
|
||||
if (thumb) {
|
||||
unsigned char patch[4] = {0xdf, 0xf8, 0x00, 0xf0};
|
||||
memcpy(data, patch, 4);
|
||||
} else {
|
||||
unsigned char patch[4] = {0x04, 0xf0, 0x1f, 0xe5};
|
||||
memcpy(data, patch, 4);
|
||||
}
|
||||
memcpy(&data[4], &target, sizeof (int));
|
||||
END_PATCH();
|
||||
}
|
||||
|
||||
void patch(void *start, unsigned char patch[]) {
|
||||
PREPARE_PATCH(start);
|
||||
memcpy(data, patch, 4);
|
||||
END_PATCH();
|
||||
}
|
87
core/src/launcher.c
Normal file
87
core/src/launcher.c
Normal file
@ -0,0 +1,87 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int starts_with(const char *s, const char *t) {
|
||||
return strncmp(s, t, strlen(t)) == 0;
|
||||
}
|
||||
|
||||
static int ends_with(const char *s, const char *t) {
|
||||
size_t slen = strlen(s);
|
||||
size_t tlen = strlen(t);
|
||||
if (tlen > slen) return 1;
|
||||
return strcmp(s + slen - tlen, t) == 0;
|
||||
}
|
||||
|
||||
#define MODS_FOLDER "./mods/"
|
||||
|
||||
static void set_and_print_env(char *name, char *value) {
|
||||
fprintf(stderr, "Set %s = %s\n", name, value);
|
||||
setenv(name, value, 1);
|
||||
}
|
||||
|
||||
static char *get_env_safe(const char *name) {
|
||||
char *ret = getenv(name);
|
||||
return ret != NULL ? ret : "";
|
||||
}
|
||||
|
||||
int main(__attribute__((unused)) int argc, char *argv[]) {
|
||||
fprintf(stderr, "Configuring Game...\n");
|
||||
|
||||
char *ld_path = NULL;
|
||||
char *cwd = getcwd(NULL, 0);
|
||||
asprintf(&ld_path, "%s:/usr/arm-linux-gnueabihf/lib:%s", cwd, get_env_safe("LD_LIBRARY_PATH"));
|
||||
free(cwd);
|
||||
set_and_print_env("LD_LIBRARY_PATH", ld_path);
|
||||
free(ld_path);
|
||||
|
||||
char *ld_preload = NULL;
|
||||
asprintf(&ld_preload, "%s", get_env_safe("LD_PRELOAD"));
|
||||
int folder_name_length = strlen(MODS_FOLDER);
|
||||
DIR *dp = opendir(MODS_FOLDER);
|
||||
if (dp != NULL) {
|
||||
struct dirent *entry = NULL;
|
||||
errno = 0;
|
||||
while (1) {
|
||||
entry = readdir(dp);
|
||||
if (entry != NULL) {
|
||||
if (starts_with(entry->d_name, "lib") && ends_with(entry->d_name, ".so")) {
|
||||
int name_length = strlen(entry->d_name);
|
||||
int total_length = folder_name_length + name_length;
|
||||
char name[total_length + 1];
|
||||
|
||||
for (int i = 0; i < folder_name_length; i++) {
|
||||
name[i] = MODS_FOLDER[i];
|
||||
}
|
||||
for (int i = 0; i < name_length; i++) {
|
||||
name[folder_name_length + i] = entry->d_name[i];
|
||||
}
|
||||
|
||||
name[total_length] = '\0';
|
||||
|
||||
asprintf(&ld_preload, "%s:%s", name, ld_preload);
|
||||
}
|
||||
} else if (errno != 0) {
|
||||
fprintf(stderr, "Error Reading Directory: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error Opening Directory: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
closedir(dp);
|
||||
set_and_print_env("LD_PRELOAD", ld_preload);
|
||||
free(ld_preload);
|
||||
|
||||
fprintf(stderr, "Starting Game...\n");
|
||||
return execve("./minecraft-pi", argv, environ);
|
||||
}
|
19
mods/CMakeLists.txt
Normal file
19
mods/CMakeLists.txt
Normal file
@ -0,0 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
|
||||
project(mods)
|
||||
|
||||
add_compile_options(-Wall -Wextra -Werror)
|
||||
|
||||
add_subdirectory(../core core)
|
||||
include_directories(../core/include)
|
||||
|
||||
add_library(compat SHARED src/compat.c)
|
||||
target_link_libraries(compat core SDL EGL GLESv1_CM GLESv2 X11 dl)
|
||||
# Force GLESv1 Link
|
||||
target_link_options(compat PRIVATE "-Wl,--no-as-needed")
|
||||
|
||||
add_library(touch SHARED src/touch.c)
|
||||
target_link_libraries(touch core dl)
|
||||
|
||||
add_library(readdir SHARED src/readdir.c)
|
||||
target_link_libraries(readdir core)
|
204
mods/src/compat.c
Normal file
204
mods/src/compat.c
Normal file
@ -0,0 +1,204 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_syswm.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <libcore/libcore.h>
|
||||
|
||||
static Display *x11_display;
|
||||
static EGLDisplay egl_display;
|
||||
static Window x11_window;
|
||||
static Window x11_root_window;
|
||||
static EGLConfig egl_config;
|
||||
static int window_loaded = 0;
|
||||
static EGLContext egl_context;
|
||||
static EGLSurface egl_surface;
|
||||
|
||||
HOOK(eglGetDisplay, EGLDisplay, (__attribute__((unused)) NativeDisplayType native_display)) {
|
||||
// Handled In ensure_x11_window()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get Reference To X Window
|
||||
static void ensure_x11_window() {
|
||||
if (!window_loaded) {
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
SDL_GetWMInfo(&info);
|
||||
|
||||
x11_display = info.info.x11.display;
|
||||
x11_window = info.info.x11.window;
|
||||
x11_root_window = RootWindow(x11_display, DefaultScreen(x11_display));
|
||||
ensure_eglGetDisplay();
|
||||
egl_display = (*real_eglGetDisplay)(x11_display);
|
||||
|
||||
window_loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(eglInitialize, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint *major, __attribute__((unused)) EGLint *minor)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(eglChooseConfig, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLint const *attrib_list, __attribute__((unused)) EGLConfig *configs, __attribute__((unused)) EGLint config_size, __attribute__((unused)) EGLint *num_config)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(eglBindAPI, EGLBoolean, (__attribute__((unused)) EGLenum api)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(eglCreateContext, EGLContext, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) EGLContext share_context, __attribute__((unused)) EGLint const *attrib_list)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(eglCreateWindowSurface, EGLSurface, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLConfig config, __attribute__((unused)) NativeWindowType native_window, __attribute__((unused)) EGLint const *attrib_list)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(eglMakeCurrent, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface draw, __attribute__((unused)) EGLSurface read, __attribute__((unused)) EGLContext context)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_Quit
|
||||
HOOK(eglDestroySurface, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_Quit
|
||||
HOOK(eglDestroyContext, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLContext context)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_Quit
|
||||
HOOK(eglTerminate, EGLBoolean, (__attribute__((unused)) EGLDisplay display)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// Handled In SDL_WM_SetCaption
|
||||
HOOK(SDL_SetVideoMode, SDL_Surface *, (__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) Uint32 flags)) {
|
||||
// Return Value Is Only Used For A NULL-Check
|
||||
return (SDL_Surface *) 1;
|
||||
}
|
||||
|
||||
// EGL Config
|
||||
EGLint const set_attrib_list[] = {
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
// Init EGL
|
||||
HOOK(SDL_WM_SetCaption, void, (const char *title, const char *icon)) {
|
||||
ensure_SDL_SetVideoMode();
|
||||
(*real_SDL_SetVideoMode)(848, 480, 32, 16);
|
||||
|
||||
ensure_SDL_WM_SetCaption();
|
||||
(*real_SDL_WM_SetCaption)(title, icon);
|
||||
|
||||
ensure_x11_window();
|
||||
|
||||
ensure_eglInitialize();
|
||||
(*real_eglInitialize)(egl_display, NULL, NULL);
|
||||
|
||||
EGLint number_of_config;
|
||||
ensure_eglChooseConfig();
|
||||
(*real_eglChooseConfig)(egl_display, set_attrib_list, &egl_config, 1, &number_of_config);
|
||||
|
||||
ensure_eglBindAPI();
|
||||
(*real_eglBindAPI)(EGL_OPENGL_ES_API);
|
||||
|
||||
ensure_eglCreateContext();
|
||||
egl_context = (*real_eglCreateContext)(egl_display, egl_config, EGL_NO_CONTEXT, NULL);
|
||||
|
||||
ensure_eglCreateWindowSurface();
|
||||
egl_surface = (*real_eglCreateWindowSurface)(egl_display, egl_config, x11_window, NULL);
|
||||
|
||||
ensure_eglMakeCurrent();
|
||||
(*real_eglMakeCurrent)(egl_display, egl_surface, egl_surface, egl_context);
|
||||
|
||||
eglSwapInterval(egl_display, 1);
|
||||
}
|
||||
|
||||
HOOK(eglSwapBuffers, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __attribute__((unused)) EGLSurface surface)) {
|
||||
ensure_x11_window();
|
||||
|
||||
ensure_eglSwapBuffers();
|
||||
EGLBoolean ret = (*real_eglSwapBuffers)(egl_display, egl_surface);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HOOK(SDL_PollEvent, int, (SDL_Event *event)) {
|
||||
ensure_SDL_PollEvent();
|
||||
int ret = (*real_SDL_PollEvent)(event);
|
||||
|
||||
// Resize EGL
|
||||
if (event != NULL && event->type == SDL_VIDEORESIZE) {
|
||||
ensure_SDL_SetVideoMode();
|
||||
(*real_SDL_SetVideoMode)(event->resize.w, event->resize.h, 32, 16);
|
||||
|
||||
// OpenGL state modification for resizing
|
||||
glViewport(0, 0, event->resize.w, event->resize.h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glOrthox(0, event->resize.w, 0, event->resize.h, -1, 1);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Terminate EGL
|
||||
HOOK(SDL_Quit, void, ()) {
|
||||
ensure_SDL_Quit();
|
||||
(*real_SDL_Quit)();
|
||||
|
||||
ensure_eglDestroyContext();
|
||||
(*real_eglDestroyContext)(egl_display, egl_context);
|
||||
ensure_eglDestroySurface();
|
||||
(*real_eglDestroySurface)(egl_display, egl_surface);
|
||||
ensure_eglTerminate();
|
||||
(*real_eglTerminate)(egl_display);
|
||||
}
|
||||
|
||||
HOOK(XTranslateCoordinates, int, (Display *display, Window src_w, Window dest_w, int src_x, int src_y, int *dest_x_return, int *dest_y_return, Window *child_return)) {
|
||||
ensure_XTranslateCoordinates();
|
||||
if (window_loaded) {
|
||||
return (*real_XTranslateCoordinates)(x11_display, x11_window, x11_root_window, src_x, src_y, dest_x_return, dest_y_return, child_return);
|
||||
} else {
|
||||
return (*real_XTranslateCoordinates)(display, src_w, dest_w, src_x, src_y, dest_x_return, dest_y_return, child_return);
|
||||
}
|
||||
}
|
||||
|
||||
HOOK(XGetWindowAttributes, int, (Display *display, Window w, XWindowAttributes *window_attributes_return)) {
|
||||
ensure_XGetWindowAttributes();
|
||||
if (window_loaded) {
|
||||
return (*real_XGetWindowAttributes)(x11_display, x11_window, window_attributes_return);
|
||||
} else {
|
||||
return (*real_XGetWindowAttributes)(display, w, window_attributes_return);
|
||||
}
|
||||
}
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Use VirGL
|
||||
__attribute__((constructor)) static void init() {
|
||||
setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
|
||||
setenv("GALLIUM_DRIVER", "virpipe", 1);
|
||||
}
|
23
mods/src/readdir.c
Normal file
23
mods/src/readdir.c
Normal file
@ -0,0 +1,23 @@
|
||||
#define _GNU_SOURCE
|
||||
#define __USE_LARGEFILE64
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <libcore/libcore.h>
|
||||
|
||||
#define FILENAME_SIZE 256
|
||||
|
||||
HOOK(readdir, struct dirent *, (DIR *dirp)) {
|
||||
struct dirent64 *original = readdir64(dirp);
|
||||
if (original == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
static struct dirent new;
|
||||
for (int i = 0; i < FILENAME_SIZE; i++) {
|
||||
new.d_name[i] = original->d_name[i];
|
||||
}
|
||||
new.d_type = original->d_type;
|
||||
return &new;
|
||||
}
|
8
mods/src/touch.c
Normal file
8
mods/src/touch.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <libcore/libcore.h>
|
||||
|
||||
__attribute__((constructor)) static void init() {
|
||||
unsigned char patch_data[4] = {0x01, 0x00, 0x50, 0xe3};
|
||||
patch((void *) 0x292fc, patch_data);
|
||||
//unsigned char patch_data_2[4] = {0x00, 0x30, 0xa0, 0xe3};
|
||||
//patch((void *) 0x3d9b8, patch_data_2);
|
||||
}
|
10
run.sh
Executable file
10
run.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
virgl_test_server &
|
||||
PID="$!"
|
||||
|
||||
sudo docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /tmp/.virgl_test:/tmp/.virgl_test -v ~/.minecraft-pi:/root/.minecraft -e DISPLAY=unix${DISPLAY} thebrokenrail/minecraft-pi
|
||||
|
||||
kill "${PID}"
|
15
scripts/build-libpng12.sh
Executable file
15
scripts/build-libpng12.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
git clone --depth 1 https://git.code.sf.net/p/libpng/code libpng -b libpng12
|
||||
|
||||
cd libpng
|
||||
|
||||
./configure --host arm-linux-gnueabihf --prefix /usr/arm-linux-gnueabihf
|
||||
|
||||
make -j$(nproc)
|
||||
make install
|
||||
|
||||
cd ../
|
||||
rm -rf libpng
|
19
scripts/build-mods.sh
Executable file
19
scripts/build-mods.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd mods
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake/toolchain.cmake ..
|
||||
make -j$(nproc)
|
||||
|
||||
cd ../../
|
||||
|
||||
mkdir minecraft-pi/mods
|
||||
cp mods/build/lib*.so minecraft-pi/mods
|
||||
|
||||
cp mods/build/core/lib*.so minecraft-pi
|
||||
cp mods/build/core/launcher minecraft-pi
|
8
scripts/download-minecraft-pi.sh
Executable file
8
scripts/download-minecraft-pi.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
URL="https://www.minecraft.net/content/dam/minecraft/edition-pi/minecraft-pi-0.1.1.tar.gz"
|
||||
|
||||
mkdir minecraft-pi
|
||||
curl "${URL}" | tar -xz --strip-components 1 -C minecraft-pi
|
Loading…
Reference in New Issue
Block a user