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