frontend: add screenshot functionality
authornotaz <notasas@gmail.com>
Sat, 12 Mar 2011 20:09:04 +0000 (22:09 +0200)
committernotaz <notasas@gmail.com>
Sun, 13 Mar 2011 22:59:31 +0000 (00:59 +0200)
Makefile
frontend/common/readpng.c
frontend/common/readpng.h
frontend/main.c
frontend/main.h
frontend/menu.c
frontend/pandora.c
frontend/plugin_lib.c
frontend/plugin_lib.h
maemo/hildon.c

index 900a5d8..2c2767a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -87,7 +87,7 @@ plugins/dfinput/%.o: CFLAGS += -Wall
 OBJS += plugins/dfinput/pad.o
 
 # gui
-OBJS += frontend/main.o frontend/plugin.o 
+OBJS += frontend/main.o frontend/plugin.o
 ifeq "$(USE_GTK)" "1"
 OBJS += maemo/hildon.o maemo/main.o
 maemo/%.o: maemo/%.c
index b7bad57..cad1217 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Gražvydas "notaz" Ignotas, 2008-2010
+ * (C) Gražvydas "notaz" Ignotas, 2008-2011
  *
  * This work is licensed under the terms of any of these licenses
  * (at your option):
@@ -9,6 +9,7 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <png.h>
 #include "readpng.h"
@@ -190,4 +191,76 @@ done:
        return ret;
 }
 
+int writepng(const char *fname, unsigned short *src, int w, int h)
+{
+       png_structp png_ptr = NULL;
+       png_infop info_ptr = NULL;
+       png_bytepp row_pointers;
+       int i, j, ret = -1;
+       FILE *f;
+
+       f = fopen(fname, "wb");
+       if (f == NULL) {
+               lprintf(__FILE__ ": failed to open \"%s\"\n", fname);
+               return -1;
+       }
+
+       row_pointers = calloc(h, sizeof(row_pointers[0]));
+       if (row_pointers == NULL)
+               goto end1;
+
+       for (i = 0; i < h; i++) {
+               unsigned char *dst = malloc(w * 3);
+               if (dst == NULL)
+                       goto end2;
+               row_pointers[i] = dst;
+               for (j = 0; j < w; j++, src++, dst += 3) {
+                       dst[0] = (*src & 0xf800) >> 8;
+                       dst[1] = (*src & 0x07e0) >> 3;
+                       dst[2] = (*src & 0x001f) << 3;
+               }
+       }
+
+       /* initialize stuff */
+       png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+       if (png_ptr == NULL) {
+               fprintf(stderr, "png_create_write_struct() failed");
+               goto end2;
+       }
+
+       info_ptr = png_create_info_struct(png_ptr);
+       if (info_ptr == NULL) {
+               fprintf(stderr, "png_create_info_struct() failed");
+               goto end3;
+       }
+
+       if (setjmp(png_jmpbuf(png_ptr)) != 0) {
+               fprintf(stderr, "error in png code\n");
+               goto end4;
+       }
+
+       png_init_io(png_ptr, f);
+
+       png_set_IHDR(png_ptr, info_ptr, w, h,
+               8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+               PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+       png_write_info(png_ptr, info_ptr);
+       png_write_image(png_ptr, row_pointers);
+       png_write_end(png_ptr, NULL);
+
+       ret = 0;
+
+end4:
+//     png_destroy_info_struct(png_ptr, &info_ptr); // freed below
+end3:
+       png_destroy_write_struct(&png_ptr, &info_ptr);
+end2:
+       for (i = 0; i < h; i++)
+               free(row_pointers[i]);
+       free(row_pointers);
+end1:
+       fclose(f);
+       return ret;
+}
 
index ce5d635..924b341 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
 #endif
 
 int readpng(void *dest, const char *fname, readpng_what what, int w, int h);
+int writepng(const char *fname, unsigned short *src, int w, int h);
 
 #ifdef __cplusplus
 }
index 32b12ea..0ed66d5 100644 (file)
@@ -13,6 +13,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <signal.h>
+#include <time.h>
 
 #include "main.h"
 #include "plugin.h"
@@ -24,6 +25,7 @@
 #include "../plugins/cdrcimg/cdrcimg.h"
 #include "common/plat.h"
 #include "common/input.h"
+#include "common/readpng.h"
 
 int ready_to_go;
 unsigned long gpuDisp;
@@ -66,6 +68,24 @@ static void CheckSubDir() {
        create_profile_dir(CHEATS_DIR);
        create_profile_dir(PATCHES_DIR);
        create_profile_dir(PCSX_DOT_DIR "cfg");
+       create_profile_dir("/screenshots/");
+}
+
+static int get_gameid_filename(char *buf, int size, const char *fmt, int i) {
+       char trimlabel[33];
+       int j;
+
+       strncpy(trimlabel, CdromLabel, 32);
+       trimlabel[32] = 0;
+       for (j = 31; j >= 0; j--)
+               if (trimlabel[j] == ' ')
+                       trimlabel[j] = 0;
+               else
+                       continue;
+
+       snprintf(buf, size, fmt, trimlabel, CdromId, i);
+
+       return 0;
 }
 
 void set_cd_image(const char *fname)
@@ -107,6 +127,7 @@ static void set_default_paths(void)
 
 void do_emu_action(void)
 {
+       char buf[MAXPATHLEN];
        int ret;
 
        emu_action_old = emu_action;
@@ -140,6 +161,25 @@ void do_emu_action(void)
                snprintf(hud_msg, sizeof(hud_msg), "FRAMESKIP %s",
                        UseFrameSkip ? "ON" : "OFF");
                break;
+       case SACTION_SCREENSHOT:
+               {
+                       void *scrbuf;
+                       int w, h, bpp;
+                       time_t t = time(NULL);
+                       struct tm *tb = localtime(&t);
+                       int ti = tb->tm_yday * 1000000 + tb->tm_hour * 10000 +
+                               tb->tm_min * 100 + tb->tm_sec;
+
+                       scrbuf = pl_prepare_screenshot(&w, &h, &bpp);
+                       get_gameid_filename(buf, sizeof(buf),
+                               "screenshots/%.32s-%.9s.%d.png", ti);
+                       ret = -1;
+                       if (scrbuf != 0 && bpp == 16)
+                               ret = writepng(buf, scrbuf, w, h);
+                       if (ret == 0)
+                               snprintf(hud_msg, sizeof(hud_msg), "SCREENSHOT TAKEN");
+                       break;
+               }
        }
        hud_new_msg = 3;
        return;
@@ -381,21 +421,8 @@ void OnFile_Exit() {
 }
 
 int get_state_filename(char *buf, int size, int i) {
-       char trimlabel[33];
-       int j;
-
-       strncpy(trimlabel, CdromLabel, 32);
-       trimlabel[32] = 0;
-       for (j = 31; j >= 0; j--)
-               if (trimlabel[j] == ' ')
-                       trimlabel[j] = 0;
-               else
-                       continue;
-
-       snprintf(buf, size, "." STATES_DIR "%.32s-%.9s.%3.3d",
-               trimlabel, CdromId, i);
-
-       return 0;
+       return get_gameid_filename(buf, size,
+               "." STATES_DIR "%.32s-%.9s.%3.3d", i);
 }
 
 int emu_check_state(int slot)
index b64bc4c..eadb3c6 100644 (file)
@@ -56,6 +56,7 @@ enum sched_action {
        SACTION_NEXT_SSLOT,
        SACTION_PREV_SSLOT,
        SACTION_TOGGLE_FSKIP,
+       SACTION_SCREENSHOT,
 };
 
 static inline void emu_set_action(enum sched_action action_)
index 63b9e2d..d16eaca 100644 (file)
@@ -667,6 +667,7 @@ me_bind_action emuctrl_actions[] =
        { "Prev Save Slot   ", 1 << SACTION_PREV_SSLOT },
        { "Next Save Slot   ", 1 << SACTION_NEXT_SSLOT },
        { "Toggle Frameskip ", 1 << SACTION_TOGGLE_FSKIP },
+       { "Take Screenshot  ", 1 << SACTION_SCREENSHOT },
        { "Enter Menu       ", 1 << SACTION_ENTER_MENU },
        { NULL,                0 }
 };
index 677784e..b4e3a42 100644 (file)
@@ -60,6 +60,7 @@ struct in_default_bind in_evdev_defbinds[] = {
        { KEY_3,        IN_BINDTYPE_EMU, SACTION_PREV_SSLOT },
        { KEY_4,        IN_BINDTYPE_EMU, SACTION_NEXT_SSLOT },
        { KEY_5,        IN_BINDTYPE_EMU, SACTION_TOGGLE_FSKIP },
+       { KEY_6,        IN_BINDTYPE_EMU, SACTION_SCREENSHOT },
        { 0, 0, 0 }
 };
 
index 5cf1ff4..46c9cbd 100644 (file)
@@ -131,6 +131,15 @@ void pl_fbdev_close(void)
        omap_enable_layer(0);
 }
 
+void *pl_prepare_screenshot(int *w, int *h, int *bpp)
+{
+       *w = pl_fbdev_w;
+       *h = pl_fbdev_h;
+       *bpp = pl_fbdev_bpp;
+
+       return pl_fbdev_buf;
+}
+
 static void update_input(void)
 {
        int actions[IN_BINDTYPE_COUNT] = { 0, };
index 53a597f..61dc3be 100644 (file)
@@ -27,8 +27,9 @@ void *pl_fbdev_set_mode(int w, int h, int bpp);
 void *pl_fbdev_flip(void);
 void  pl_fbdev_close(void);
 
-void pl_text_out16(int x, int y, const char *texto, ...);
-void pl_start_watchdog(void);
+void  pl_text_out16(int x, int y, const char *texto, ...);
+void  pl_start_watchdog(void);
+void *pl_prepare_screenshot(int *w, int *h, int *bpp);
 
 struct rearmed_cbs {
        void  (*pl_get_layer_pos)(int *x, int *y, int *w, int *h);
index 37e67af..342ac19 100644 (file)
@@ -211,6 +211,16 @@ static void pl_get_layer_pos(int *x, int *y, int *w, int *h)
        *h = 640;
 }
 
+void *pl_prepare_screenshot(int *w, int *h, int *bpp)
+{
+       return NULL;
+}
+
+int writepng()
+{
+       return -1;
+}
+
 extern int UseFrameSkip; // hmh
 
 const struct rearmed_cbs pl_rearmed_cbs = {