aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorneonloop2021-08-13 22:43:46 +0000
committerneonloop2021-08-13 22:43:46 +0000
commitd10f04ae3101ddcea792d5534de8f4755cdfa0a5 (patch)
tree6163409998c60827d572eb3fe072a1a49bb558b1
parent96f0836dc0f6715dabc98f53ae1c4383286764d7 (diff)
downloadpicoarch-d10f04ae3101ddcea792d5534de8f4755cdfa0a5.tar.gz
picoarch-d10f04ae3101ddcea792d5534de8f4755cdfa0a5.tar.bz2
picoarch-d10f04ae3101ddcea792d5534de8f4755cdfa0a5.zip
Adds screenshots to savestates
-rw-r--r--core.c3
-rw-r--r--menu.c51
-rw-r--r--menu.h2
-rw-r--r--plat.h3
-rw-r--r--plat_sdl.c94
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 <SDL/SDL.h>
#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());