mirror of
https://github.com/libretro/mgba.git
synced 2024-11-24 16:40:00 +00:00
Add screenshot capability
This commit is contained in:
parent
103bef17c9
commit
bbe52bf632
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
76
src/util/png-io.c
Normal 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
16
src/util/png-io.h
Normal 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
|
Loading…
Reference in New Issue
Block a user