Add screenshot capability

This commit is contained in:
Jeffrey Pfau 2014-07-25 05:44:20 -07:00
parent 103bef17c9
commit bbe52bf632
6 changed files with 118 additions and 1 deletions

View File

@ -85,7 +85,7 @@ endif()
source_group("ARM debugger" FILES ${DEBUGGER_SRC})
add_library(${BINARY_NAME} SHARED ${ARM_SRC} ${GBA_SRC} ${DEBUGGER_SRC} ${RENDERER_SRC} ${UTIL_SRC} ${VFS_SRC} ${OS_SRC})
target_link_libraries(${BINARY_NAME} m ${DEBUGGER_LIB} ${OS_LIB} ${DEPENDENCY_LIB})
target_link_libraries(${BINARY_NAME} m ${DEBUGGER_LIB} ${OS_LIB} ${DEPENDENCY_LIB} png)
if(BUILD_SDL)
add_subdirectory(${CMAKE_SOURCE_DIR}/src/platform/sdl ${CMAKE_BINARY_DIR}/sdl)

View File

@ -77,6 +77,7 @@ int main(int argc, char** argv) {
renderer.events.fullscreen = graphicsOpts.fullscreen;
renderer.events.windowUpdated = 0;
#endif
renderer.events.renderer = &renderer.d;
if (!_GBASDLInit(&renderer)) {
freeOptions(&opts);

View File

@ -5,6 +5,9 @@
#include "gba-rr.h"
#include "gba-serialize.h"
#include "gba-video.h"
#include "renderers/video-software.h"
#include "util/png-io.h"
#include "util/vfs.h"
#if SDL_VERSION_ATLEAST(2, 0, 0) && defined(__APPLE__)
#define GUI_MOD KMOD_GUI
@ -15,6 +18,8 @@
#define SDL_BINDING_KEY 0x53444C4B
#define SDL_BINDING_BUTTON 0x53444C42
static void _takeScreenshot(struct GBAThread*, struct GBASDLEvents*);
bool GBASDLInitEvents(struct GBASDLEvents* context) {
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
return false;
@ -74,6 +79,13 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
}
return;
case SDLK_F12:
if (event->type == SDL_KEYDOWN) {
GBAThreadInterrupt(context);
_takeScreenshot(context, sdlContext);
GBAThreadContinue(context);
}
return;
case SDLK_TAB:
context->sync.audioWait = event->type != SDL_KEYDOWN;
return;
@ -249,3 +261,12 @@ void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLEvents* sdlContex
_GBASDLHandleJoyHat(context, &event->jhat);
}
}
static void _takeScreenshot(struct GBAThread* context, struct GBASDLEvents* sdlContext) {
struct VFile* vf = context->stateDir->openFile(context->stateDir, "screenshot.png", O_CREAT | O_WRONLY);
png_structp png = PNGWriteOpen(vf);
png_infop info = PNGWriteHeader(png, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
PNGWritePixels(png, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, 256, sdlContext->renderer->outputBuffer);
PNGWriteClose(png, info);
vf->close(vf);
}

View File

@ -7,8 +7,11 @@
#include <SDL.h>
struct GBAVideoSoftwareRenderer;
struct GBASDLEvents {
struct GBAInputMap* bindings;
struct GBAVideoSoftwareRenderer* renderer;
SDL_Joystick* joystick;
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Window* window;

76
src/util/png-io.c Normal file
View File

@ -0,0 +1,76 @@
#include "util/png-io.h"
#include "vfs.h"
static void _pngWrite(png_structp png, png_bytep buffer, png_size_t size) {
struct VFile* vf = png_get_io_ptr(png);
size_t written = vf->write(vf, buffer, size);
if (written != size) {
png_error(png, "Could not write PNG");
}
}
png_structp PNGWriteOpen(struct VFile* source) {
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (!png) {
return 0;
}
if (setjmp(png_jmpbuf(png))) {
png_destroy_write_struct(&png, 0);
return 0;
}
png_set_write_fn(png, source, _pngWrite, 0);
return png;
}
png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height) {
png_infop info = png_create_info_struct(png);
if (!info) {
return 0;
}
png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png, info);
return info;
}
bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned stride, void* pixels) {
png_bytep row = malloc(sizeof(png_bytep) * width * 3);
if (!row) {
return false;
}
png_bytep pixelData = pixels;
if (setjmp(png_jmpbuf(png))) {
free(row);
return false;
}
unsigned i;
for (i = 0; i < height; ++i) {
unsigned x;
for (x = 0; x < width; ++x) {
row[x * 3] = pixelData[stride * i * 4 + x * 4];
row[x * 3 + 1] = pixelData[stride * i * 4 + x * 4 + 1];
row[x * 3 + 2] = pixelData[stride * i * 4 + x * 4 + 2];
}
png_write_row(png, row);
}
free(row);
return true;
}
bool PNGWriteCustomChunk(png_structp png, const char* name, size_t size, void* data) {
char realName[5];
strncpy(realName, name, 4);
realName[0] = tolower(realName[0]);
realName[1] = tolower(realName[1]);
realName[4] = '\0';
if (setjmp(png_jmpbuf(png))) {
return false;
}
png_write_chunk(png, (png_const_bytep) realName, data, size);
return true;
}
void PNGWriteClose(png_structp png, png_infop info) {
png_write_end(png, info);
png_destroy_write_struct(&png, &info);
}

16
src/util/png-io.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef PNG_IO_H
#define PNG_IO_H
#include "common.h"
#include <png.h>
struct VFile;
png_structp PNGWriteOpen(struct VFile* source);
png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height);
bool PNGWritePixels(png_structp png, unsigned width, unsigned height, unsigned stride, void* pixels);
bool PNGWriteCustomChunk(png_structp png, const char* name, size_t size, void* data);
void PNGWriteClose(png_structp png, png_infop info);
#endif