From d10f04ae3101ddcea792d5534de8f4755cdfa0a5 Mon Sep 17 00:00:00 2001 From: neonloop Date: Fri, 13 Aug 2021 22:43:46 +0000 Subject: Adds screenshots to savestates --- core.c | 3 ++ menu.c | 51 +++++++++++++++++++++++++++++----- menu.h | 2 ++ plat.h | 3 ++ plat_sdl.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 137 insertions(+), 16 deletions(-) diff --git a/core.c b/core.c index 46c038f..c4c9e13 100644 --- a/core.c +++ b/core.c @@ -203,6 +203,9 @@ int state_write(void) { PA_ERROR("Error writing state data to file\n"); goto error; } + + plat_dump_screen(filename); + ret = 0; error: if (state) diff --git a/menu.c b/menu.c index 03f20d5..6ada18c 100644 --- a/menu.c +++ b/menu.c @@ -6,6 +6,8 @@ #include "plat.h" #include "scale.h" +static int drew_alt_bg = 0; + #define MENU_ALIGN_LEFT 0 #define MENU_X2 0 @@ -203,6 +205,11 @@ static int mh_rmcfg(int id, int keys) return 1; } +static void draw_src_bg(void) { + memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menubg_src_h * g_menubg_src_pp * sizeof(uint16_t)); + menu_darken_bg(g_menubg_ptr, g_menubg_src_ptr, g_menubg_src_h * g_menubg_src_pp, 0); +} + static int menu_loop_core_options_page(int offset, int keys) { static int sel = 0; menu_entry *e_menu_core_options; @@ -422,6 +429,39 @@ static menu_entry e_menu_main[] = static void draw_savestate_bg(int slot) { + char filename[MAX_PATH]; + int w, h, bpp; + size_t bufsize = SCREEN_PITCH * SCREEN_HEIGHT; + void *buf = calloc(bufsize, sizeof(char)); + + if (!buf) { + PA_WARN("Couldn't allocate savestate background"); + goto finish; + } + state_file_name(filename, MAX_PATH, slot); + + if (plat_load_screen(filename, buf, bufsize, &w, &h, &bpp)) + goto finish; + + if (bpp == sizeof(uint16_t)) { + menu_darken_bg(g_menubg_ptr, buf, w * h, 0); + drew_alt_bg = 1; + } + +finish: + if (buf) + free(buf); +} + +void menu_begin(void) +{ + if (!drew_alt_bg) + draw_src_bg(); +} + +void menu_end(void) +{ + drew_alt_bg = 0; } void menu_loop(void) @@ -440,16 +480,11 @@ void menu_loop(void) me_enable(e_menu_main, MA_MAIN_LOAD_STATE, mmenu == NULL); } #endif - - memcpy(g_menubg_ptr, g_menuscreen_ptr, g_menuscreen_h * g_menuscreen_pp * sizeof(uint16_t)); - - menu_darken_bg(g_menubg_ptr, g_menubg_ptr, g_menuscreen_h * g_menuscreen_pp, 0); me_loop_d(e_menu_main, &sel, NULL, NULL); /* wait until menu, ok, back is released */ while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK)) ; - memset(g_menubg_ptr, 0, g_menuscreen_h * g_menuscreen_pp * sizeof(uint16_t)); /* Force the hud to clear */ plat_video_set_msg(" "); @@ -460,8 +495,8 @@ int menu_init(void) { menu_init_base(); - g_menubg_src_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1); - g_menubg_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1); + g_menubg_src_ptr = calloc(g_menubg_src_pp * g_menubg_src_h, sizeof(uint16_t)); + g_menubg_ptr = calloc(g_menuscreen_w * g_menuscreen_pp, sizeof(uint16_t)); if (g_menubg_src_ptr == NULL || g_menubg_ptr == NULL) { fprintf(stderr, "OOM\n"); return -1; @@ -473,10 +508,12 @@ void menu_finish(void) { if (g_menubg_src_ptr) { free(g_menubg_src_ptr); + g_menubg_src_ptr = NULL; } if (g_menubg_ptr) { free(g_menubg_ptr); + g_menubg_ptr = NULL; } } diff --git a/menu.h b/menu.h index 9b9739d..b9117ce 100644 --- a/menu.h +++ b/menu.h @@ -6,6 +6,8 @@ int menu_init(void); void menu_loop(void); +void menu_begin(void); +void menu_end(void); void menu_finish(void); #endif diff --git a/plat.h b/plat.h index 6b84f1f..f116d1c 100644 --- a/plat.h +++ b/plat.h @@ -13,7 +13,10 @@ struct audio_frame { int plat_init(void); void plat_finish(void); void plat_minimize(void); + void *plat_prepare_screenshot(int *w, int *h, int *bpp); +int plat_dump_screen(const char *filename); +int plat_load_screen(const char *filename, void *buf, size_t buf_size, int *w, int *h, int *bpp); void plat_video_open(void); void plat_video_set_msg(const char *new_msg); diff --git a/plat_sdl.c b/plat_sdl.c index 4726535..ec5b683 100644 --- a/plat_sdl.c +++ b/plat_sdl.c @@ -1,8 +1,8 @@ #include #include "core.h" #include "libpicofe/fonts.h" -#include "libpicofe/menu.h" #include "libpicofe/plat.h" +#include "menu.h" #include "plat.h" #include "scale.h" @@ -64,32 +64,105 @@ void *plat_prepare_screenshot(int *w, int *h, int *bpp) if (h) *h = SCREEN_HEIGHT; if (bpp) *bpp = SCREEN_BPP; - return g_menuscreen_ptr; + return screen->pixels; +} + +int plat_dump_screen(const char *filename) { + char imgname[MAX_PATH]; + int ret = -1; + SDL_Surface *surface = NULL; + + snprintf(imgname, MAX_PATH, "%s.bmp", filename); + + if (g_menuscreen_ptr) { + surface = SDL_CreateRGBSurfaceFrom(g_menubg_src_ptr, + g_menubg_src_w, + g_menubg_src_h, + 16, + g_menubg_src_w * sizeof(uint16_t), + 0xF800, 0x07E0, 0x001F, 0x0000); + if (surface) { + ret = SDL_SaveBMP(surface, imgname); + SDL_FreeSurface(surface); + } + } else { + ret = SDL_SaveBMP(screen, imgname); + } + + return ret; } +int plat_load_screen(const char *filename, void *buf, size_t buf_size, int *w, int *h, int *bpp) { + int ret = -1; + char imgname[MAX_PATH]; + SDL_Surface *imgsurface = NULL; + SDL_Surface *surface = NULL; + + snprintf(imgname, MAX_PATH, "%s.bmp", filename); + imgsurface = SDL_LoadBMP(imgname); + if (!imgsurface) + goto finish; + + surface = SDL_DisplayFormat(imgsurface); + if (!surface) + goto finish; + + if (surface->pitch > SCREEN_PITCH || + surface->h > SCREEN_HEIGHT || + surface->w == 0 || + surface->h * surface->pitch > buf_size) + goto finish; + + memcpy(buf, surface->pixels, surface->pitch * surface->h); + *w = surface->w; + *h = surface->h; + *bpp = surface->pitch / surface->w; + + ret = 0; + +finish: + if (imgsurface) + SDL_FreeSurface(imgsurface); + if (surface) + SDL_FreeSurface(surface); + return ret; +} + + void plat_video_menu_enter(int is_rom_loaded) { + SDL_LockSurface(screen); + memcpy(g_menubg_src_ptr, screen->pixels, g_menubg_src_h * g_menubg_src_pp * sizeof(uint16_t)); + SDL_UnlockSurface(screen); + g_menuscreen_ptr = fb_flip(); } void plat_video_menu_begin(void) { - g_menuscreen_ptr = fb_flip(); + SDL_LockSurface(screen); + menu_begin(); } void plat_video_menu_end(void) { + menu_end(); + SDL_UnlockSurface(screen); g_menuscreen_ptr = fb_flip(); } void plat_video_menu_leave(void) { + memset(g_menubg_src_ptr, 0, g_menuscreen_h * g_menuscreen_pp * sizeof(uint16_t)); + SDL_LockSurface(screen); - memset(g_menuscreen_ptr, 0, SCREEN_WIDTH * SCREEN_HEIGHT * SCREEN_BPP); + memset(screen->pixels, 0, g_menuscreen_h * g_menuscreen_pp * sizeof(uint16_t)); SDL_UnlockSurface(screen); - g_menuscreen_ptr = fb_flip(); + fb_flip(); SDL_LockSurface(screen); - memset(g_menuscreen_ptr, 0, SCREEN_WIDTH * SCREEN_HEIGHT * SCREEN_BPP); + memset(screen->pixels, 0, g_menuscreen_h * g_menuscreen_pp * sizeof(uint16_t)); SDL_UnlockSurface(screen); + + g_menuscreen_ptr = NULL; } void plat_video_open(void) @@ -117,7 +190,7 @@ void plat_video_process(const void *data, unsigned width, unsigned height, size_ void plat_video_flip(void) { - g_menuscreen_ptr = fb_flip(); + fb_flip(); msg[0] = 0; } @@ -253,7 +326,6 @@ int plat_init(void) { SDL_Init(SDL_INIT_VIDEO); screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP * 8, SDL_SWSURFACE); - if (screen == NULL) { PA_ERROR("%s, failed to set video mode\n", __func__); return -1; @@ -264,7 +336,11 @@ int plat_init(void) g_menuscreen_w = SCREEN_WIDTH; g_menuscreen_h = SCREEN_HEIGHT; g_menuscreen_pp = SCREEN_WIDTH; - g_menuscreen_ptr = fb_flip(); + g_menuscreen_ptr = NULL; + + g_menubg_src_w = SCREEN_WIDTH; + g_menubg_src_h = SCREEN_HEIGHT; + g_menubg_src_pp = SCREEN_WIDTH; if (in_sdl_init(&in_sdl_platform_data, plat_sdl_event_handler)) { PA_ERROR("SDL input failed to init: %s\n", SDL_GetError()); -- cgit v1.2.3