From cb36a28b09fb4a7d7b4d9f2e143e500bf6c90306 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Fri, 20 Dec 2013 09:17:15 +0100
Subject: [PATCH] Add a very crude screenshot function (press F3)

Files are named after the current date+time (down to seconds),
and written to the gameFolder directory.
---
 src/eventthread.cpp |  3 +++
 src/eventthread.h   |  5 ++++-
 src/graphics.cpp    | 42 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/eventthread.cpp b/src/eventthread.cpp
index 699155e..89774ce 100644
--- a/src/eventthread.cpp
+++ b/src/eventthread.cpp
@@ -185,6 +185,9 @@ void EventThread::process(RGSSThreadData &rtData)
 				break;
 			}
 
+			if (event.key.keysym.scancode == SDL_SCANCODE_F3)
+				rtData.rqScreenshot = true;
+
 			keyStates[event.key.keysym.scancode] = true;
 			break;
 
diff --git a/src/eventthread.h b/src/eventthread.h
index bbe32cc..e76a73f 100644
--- a/src/eventthread.h
+++ b/src/eventthread.h
@@ -176,6 +176,8 @@ struct RGSSThreadData
 
 	QByteArray rgssErrorMsg;
 
+	volatile bool rqScreenshot;
+
 	RGSSThreadData(EventThread *ethread,
 	                 const char *argv0,
 	                 SDL_Window *window)
@@ -184,7 +186,8 @@ struct RGSSThreadData
 	      ethread(ethread),
 	      argv0(argv0),
 	      window(window),
-	      sizeResoRatio(1, 1)
+	      sizeResoRatio(1, 1),
+	      rqScreenshot(false)
 	{}
 };
 
diff --git a/src/graphics.cpp b/src/graphics.cpp
index 331e84d..187af91 100644
--- a/src/graphics.cpp
+++ b/src/graphics.cpp
@@ -37,8 +37,10 @@
 
 #include <SDL_video.h>
 #include <SDL_timer.h>
+#include <SDL_image.h>
 
 #include <time.h>
+#include <sys/time.h>
 #include <algorithm>
 
 struct PingPong
@@ -513,6 +515,44 @@ struct GraphicsPrivate
 
 		swapGLBuffer();
 	}
+
+	void writeScreenshot(const char *filename)
+	{
+		int bpp;
+		uint32_t rm, gm, bm, am;
+		SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &rm, &gm, &bm, &am);
+
+		/* Discard alpha channel because it might have bogus values */
+		SDL_Surface *screenshot =
+		        SDL_CreateRGBSurface(0, scRes.x, scRes.y, bpp, rm, gm, bm, 0);
+
+		screen.getPP().bindLastBuffer();
+
+		glReadPixels(0, 0, scSize.x, scSize.y, GL_RGBA, GL_UNSIGNED_BYTE, screenshot->pixels);
+
+		IMG_SavePNG(screenshot, filename);
+
+		SDL_FreeSurface(screenshot);
+	}
+
+	void checkScreenshotRq()
+	{
+		if (!threadData->rqScreenshot)
+			return;
+
+		threadData->rqScreenshot = false;
+
+		struct timeval tv;
+		gettimeofday(&tv, 0);
+		struct tm tm = *localtime(&tv.tv_sec);
+
+		char filename[32];
+
+		snprintf(filename, sizeof(filename), "%d%02d%02d-%02d%02d%02d.png",
+		         tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+		writeScreenshot(filename);
+	}
 };
 
 Graphics::Graphics(RGSSThreadData *data)
@@ -536,6 +576,8 @@ void Graphics::update()
 //	p->cpuTimer->endTiming();
 //	p->gpuTimer->startTiming();
 
+	p->checkScreenshotRq();
+
 	if (p->frozen)
 		return;