Add Screenshot Support VIA F2

This commit is contained in:
TheBrokenRail 2020-10-04 16:45:00 -04:00
parent b4d4c6e584
commit 7f1506ee2b
7 changed files with 86 additions and 19 deletions

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -1,5 +1,10 @@
#define _GNU_SOURCE
#include <time.h>
#include <unistd.h>
#include <FreeImage.h>
#include <SDL/SDL.h>
#include <SDL/SDL_syswm.h>
#include <EGL/egl.h>
@ -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);
}

View File

@ -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);
}

View File

@ -40,16 +40,9 @@ extern "C" {
}
std::vector<char> 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() {