From 7f1506ee2bcae1f7b9cc9b7c730c99f0e70bc62e Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Sun, 4 Oct 2020 16:45:00 -0400 Subject: [PATCH] Add Screenshot Support VIA F2 --- Dockerfile | 8 ++--- core/src/launcher.c | 6 ++++ mods/CMakeLists.txt | 2 +- mods/src/compat.c | 74 ++++++++++++++++++++++++++++++++++++++++++--- mods/src/core.c | 2 +- mods/src/extra.c | 4 +++ mods/src/extra.cpp | 9 +----- 7 files changed, 86 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index bc322d52..04d82803 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,10 +2,10 @@ 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 \ + apt-get update && \ + apt-get upgrade -y && \ + 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 libfreeimage-dev:armhf 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 diff --git a/core/src/launcher.c b/core/src/launcher.c index 15d3c690..de730f31 100644 --- a/core/src/launcher.c +++ b/core/src/launcher.c @@ -102,6 +102,12 @@ static void load(char **ld_path, char **ld_preload, char *folder) { int main(__attribute__((unused)) int argc, char *argv[]) { fprintf(stderr, "Configuring Game...\n"); + // Create Screenshots Folder + char *screenshots_cmd = NULL; + asprintf(&screenshots_cmd, "mkdir -p %s/.minecraft/screenshots", getenv("HOME")); + system(screenshots_cmd); + free(screenshots_cmd); + char *ld_path = NULL; // Start Configuring LD_LIBRARY_PATH diff --git a/mods/CMakeLists.txt b/mods/CMakeLists.txt index fb1fb478..6adb3468 100644 --- a/mods/CMakeLists.txt +++ b/mods/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(extra SHARED src/extra.c src/extra.cpp) target_link_libraries(extra core dl) add_library(compat SHARED src/compat.c) -target_link_libraries(compat core extra SDL EGL GLESv1_CM GLESv2 X11 dl) +target_link_libraries(compat core extra SDL EGL GLESv1_CM GLESv2 X11 dl freeimage) # Force GLESv1 Link target_link_options(compat PRIVATE "-Wl,--no-as-needed") diff --git a/mods/src/compat.c b/mods/src/compat.c index 4bcde0f8..99fd55f2 100644 --- a/mods/src/compat.c +++ b/mods/src/compat.c @@ -1,5 +1,10 @@ #define _GNU_SOURCE +#include +#include + +#include + #include #include #include @@ -88,7 +93,7 @@ HOOK(eglTerminate, EGLBoolean, (__attribute__((unused)) EGLDisplay display)) { } // 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)) { +HOOK(SDL_SetVideoMode, SDL_Surface *, (__attribute__((unused)) int width, __attribute__((unused)) int height, __attribute__((unused)) int bpp, __attribute__((unused)) uint32_t flags)) { // Return Value Is Only Used For A NULL-Check return (SDL_Surface *) 1; } @@ -106,13 +111,17 @@ EGLint const set_attrib_list[] = { #define WINDOW_VIDEO_FLAGS SDL_RESIZABLE #define FULLSCREEN_VIDEO_FLAGS SDL_FULLSCREEN +#define BPP 32 + // Init EGL HOOK(SDL_WM_SetCaption, void, (const char *title, const char *icon)) { // Enable Unicode SDL_EnableUNICODE(SDL_ENABLE); + FreeImage_Initialise(0); + ensure_SDL_SetVideoMode(); - sdl_surface = (*real_SDL_SetVideoMode)(848, 480, 32, WINDOW_VIDEO_FLAGS); + sdl_surface = (*real_SDL_SetVideoMode)(848, 480, BPP, WINDOW_VIDEO_FLAGS); ensure_SDL_WM_SetCaption(); (*real_SDL_WM_SetCaption)(title, icon); @@ -149,10 +158,10 @@ HOOK(eglSwapBuffers, EGLBoolean, (__attribute__((unused)) EGLDisplay display, __ } static void resize(int width, int height, int fullscreen) { - Uint32 flags = fullscreen ? FULLSCREEN_VIDEO_FLAGS : WINDOW_VIDEO_FLAGS; + uint32_t flags = fullscreen ? FULLSCREEN_VIDEO_FLAGS : WINDOW_VIDEO_FLAGS; ensure_SDL_SetVideoMode(); - sdl_surface = (*real_SDL_SetVideoMode)(width, height, 32, flags); + sdl_surface = (*real_SDL_SetVideoMode)(width, height, BPP, flags); // OpenGL state modification for resizing glViewport(0, 0, width, height); @@ -199,13 +208,65 @@ static void toggle_fullscreen() { is_fullscreen = !is_fullscreen; } +// 4 (Year + 1 (Hyphen) + 2 (Month) + 1 (Hyphen) + 2 (Day) + 1 (Underscore) + 2 (Hour) + 1 (Period) + 2 (Minute) + 1 (Period) + 2 (Second) + 1 (Terminator) +#define TIME_SIZE 20 + +static void screenshot() { + time_t rawtime; + struct tm *timeinfo; + + time(&rawtime); + timeinfo = localtime(&rawtime); + char time[TIME_SIZE]; + strftime(time, TIME_SIZE, "%Y-%m-%d_%H.%M.%S", timeinfo); + + char *screenshots = NULL; + asprintf(&screenshots, "%s/.minecraft/screenshots", getenv("HOME")); + + int num = 1; + char *file = NULL; + asprintf(&file, "%s/%s.png", screenshots, time); + while (access(file, F_OK) != -1) { + asprintf(&file, "%s/%s-%i.png", screenshots, time, num); + num++; + } + + int line_size = sdl_surface->w * 3; + int size = sdl_surface->h * line_size; + + unsigned char pixels[size]; + glReadPixels(0, 0, sdl_surface->w, sdl_surface->h, GL_RGB, GL_UNSIGNED_BYTE, pixels); + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + // Swap Red And Blue + for (int i = 0; i < (size / 3); i++) { + int pixel = i * 3; + int red = pixels[pixel]; + int blue = pixels[pixel + 2]; + pixels[pixel] = blue; + pixels[pixel + 2] = red; + } +#endif + + FIBITMAP *image = FreeImage_ConvertFromRawBits(pixels, sdl_surface->w, sdl_surface->h, line_size, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0); + if (!FreeImage_Save(FIF_PNG, image, file, 0)) { + fprintf(stderr, "Screenshot Failed: %s\n", file); + } else { + fprintf(stderr, "Screenshot Saved: %s\n", file); + } + FreeImage_Unload(image); + + free(file); + free(screenshots); +} + HOOK(SDL_PollEvent, int, (SDL_Event *event)) { // Poll Events ensure_SDL_PollEvent(); int ret = (*real_SDL_PollEvent)(event); // Resize EGL - if (event != NULL) { + if (event != NULL && ret == 1) { int handled = 0; if (event->type == SDL_VIDEORESIZE) { @@ -215,6 +276,9 @@ HOOK(SDL_PollEvent, int, (SDL_Event *event)) { if (event->key.keysym.sym == SDLK_F11) { toggle_fullscreen(); handled = 1; + } else if (event->key.keysym.sym == SDLK_F2) { + screenshot(); + handled = 1; } else { key_press((char) event->key.keysym.unicode); } diff --git a/mods/src/core.c b/mods/src/core.c index 7f7725c3..52fc7634 100644 --- a/mods/src/core.c +++ b/mods/src/core.c @@ -44,7 +44,7 @@ void revert_overwrite(void *start, void *original) { // Insert Original Value _patch(NULL, -1, start, original); _patch(NULL, -1, start + 4, original + 4); - + // Complete Memory Swap memcpy(original, temp, ORIGINAL_SIZE); free(temp); diff --git a/mods/src/extra.c b/mods/src/extra.c index 89ad16ac..cf4f9f9c 100644 --- a/mods/src/extra.c +++ b/mods/src/extra.c @@ -202,4 +202,8 @@ __attribute__((constructor)) static void init() { unsigned char autojump_patch[4] = {0x00, 0x30, 0xa0, 0xe3}; patch((void *) 0x44b90, autojump_patch); } + + // Fix Segmentation Fault + unsigned char segfault_patch[4] = {0x03, 0x00, 0x00, 0xea}; + patch((void *) 0x4a630, segfault_patch); } diff --git a/mods/src/extra.cpp b/mods/src/extra.cpp index 72418139..2eea159b 100644 --- a/mods/src/extra.cpp +++ b/mods/src/extra.cpp @@ -40,16 +40,9 @@ extern "C" { } std::vector input; - int count = 0; void key_press(char key) { if (is_valid_key(key)) { - // Keys Are Sent Twice - if (count > 0) { - count = 0; - } else { - input.push_back(key); - count++; - } + input.push_back(key); } } void clear_input() {