diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dd4821..6fc8abf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ target_sources(xsystem4 PRIVATE src/resume.c src/savedata.c src/scene.c + src/screenshot.c src/sprite.c src/swf.c src/system4.c diff --git a/include/xsystem4.h b/include/xsystem4.h index ce44d4c..28c27fe 100644 --- a/include/xsystem4.h +++ b/include/xsystem4.h @@ -81,6 +81,8 @@ char *savedir_path(const char *path); void get_date(int *year, int *month, int *mday, int *wday); void get_time(int *hour, int *min, int *sec, int *ms); +void screenshot_save(void); + #ifndef XSYS4_DATA_DIR #define XSYS4_DATA_DIR "/usr/local/share/xsystem4" #endif diff --git a/src/input.c b/src/input.c index 94825f2..bdd2cc9 100644 --- a/src/input.c +++ b/src/input.c @@ -609,12 +609,16 @@ void handle_events(void) handle_window_event(&e); break; case SDL_KEYDOWN: - if (e.key.keysym.scancode == SDL_SCANCODE_F9) + if (e.key.keysym.scancode == SDL_SCANCODE_F9) { vm_stack_trace(); - if (e.key.keysym.scancode == SDL_SCANCODE_F11) { + } else if (e.key.keysym.scancode == SDL_SCANCODE_F11) { uint32_t flag = SDL_WINDOW_FULLSCREEN_DESKTOP; bool fs = SDL_GetWindowFlags(sdl.window) & flag; SDL_SetWindowFullscreen(sdl.window, fs ? 0 : flag); + } else if (e.key.keysym.scancode == SDL_SCANCODE_S) { + if (e.key.keysym.mod & (KMOD_LALT | KMOD_RALT)) { + screenshot_save(); + } } // fallthrough case SDL_KEYUP: diff --git a/src/meson.build b/src/meson.build index 08dd2a4..47aac8a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,6 +28,7 @@ xsystem4 = [version_h, 'resume.c', 'savedata.c', 'scene.c', + 'screenshot.c', 'sprite.c', 'swf.c', 'system4.c', diff --git a/src/screenshot.c b/src/screenshot.c new file mode 100644 index 0000000..06ce8b4 --- /dev/null +++ b/src/screenshot.c @@ -0,0 +1,140 @@ +/* Copyright (C) 2019 Nunuhara Cabbage + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "system4.h" +#include "system4/cg.h" +#include "system4/file.h" +#include "gfx/gfx.h" +#include "xsystem4.h" + +static char *default_filename(void) +{ + time_t t = time(NULL); + struct tm *tm = localtime(&t); + char datetime[128]; + strftime(datetime, sizeof(datetime), "%Y%m%d_%H%M%S", tm); + + // FIXME: Earlier games use "[gamedir]/Snapshot/", but later games save under + // "Documents/AliceSoft/[gamename]/Screenshot/" + char name[PATH_MAX]; + snprintf(name, sizeof(name), "Snapshot/%s_%s.png", config.game_name, datetime); + return gamedir_path(name); +} + +#ifdef _WIN32 + +void screenshot_save(void) +{ + +} + +#else +#ifdef __ANDROID__ + +void screenshot_save(void) +{ + +} + +#else + +static bool have_zenity(void) +{ + FILE *fp = popen("zenity --version", "r"); + if (!fp) + return false; + + char line[256]; + while (fgets(line, sizeof(line), fp)) + printf("%s", line); + if (pclose(fp) != 0) + return false; + return true; +} + +static char *zenity_get_filename(const char *dflt) +{ + char buf[PATH_MAX + 64]; + snprintf(buf, sizeof(buf), "zenity --file-selection --filename=\"%s\" --save", dflt); + + FILE *fp = popen(buf, "r"); + if (!fp) + return NULL; + + // read filename + char *filename = fgets(buf, sizeof(buf), fp); + if (filename && *filename) { + filename = xstrdup(filename); + + // delete trailing newline + size_t len = strlen(filename); + if (filename[len-1] == '\n') + filename[len-1] = '\0'; + } else { + filename = NULL; + } + + // empty pipe and close + while (fgets(buf, sizeof(buf), fp)) + /* nothing */; + pclose(fp); + + return filename; +} + +void screenshot_save(void) +{ + // get filename + char *name = default_filename(); + if (have_zenity()) { + char *tmp = zenity_get_filename(name); + free(name); + name = tmp; + if (!name) + return; + } + + // create directory + char *dir = path_dirname(name); + if (mkdir_p(dir)) { + WARNING("mkdir_p: %s", strerror(errno)); + free(name); + return; + } + + // save screenshot + gfx_save_texture(gfx_main_surface(), name, ALCG_PNG); + + // XXX: this uses zenity on wayland, so there is no confirmation + // that anything happened if zenity is not installed + char msg[PATH_MAX + 64]; + snprintf(msg, sizeof(msg), "Screenshot saved to %s", name); + SDL_ShowSimpleMessageBox(0, "xsystem4", msg, NULL); + NOTICE("%s", msg); + + free(name); +} + +#endif // __ANDROID__ +#endif // _WIN32