all repos — mgba @ 532261af2c689bb1fc1c722c5a58950fbaae8488

mGBA Game Boy Advance Emulator

GBA: Move screenshot functionality from Thread to Serialize
Jeffrey Pfau jeffrey@endrift.com
Mon, 14 Sep 2015 23:25:53 -0700
commit

532261af2c689bb1fc1c722c5a58950fbaae8488

parent

03d97baeec34aed9fb54b8b8d79cfc74a7528456

M src/gba/serialize.csrc/gba/serialize.c

@@ -432,3 +432,25 @@

void GBARewindAll(struct GBAThread* thread) { GBARewind(thread, thread->rewindBufferSize); } + +void GBATakeScreenshot(struct GBA* gba, struct VDir* dir) { +#ifdef USE_PNG + unsigned stride; + const void* pixels = 0; + struct VFile* vf = VDirOptionalOpenIncrementFile(dir, gba->activeFile, "screenshot", "-", ".png", O_CREAT | O_TRUNC | O_WRONLY); + bool success = false; + if (vf) { + gba->video.renderer->getPixels(gba->video.renderer, &stride, &pixels); + png_structp png = PNGWriteOpen(vf); + png_infop info = PNGWriteHeader(png, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); + success = PNGWritePixels(png, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, stride, pixels); + PNGWriteClose(png, info); + vf->close(vf); + } + if (success) { + GBALog(gba, GBA_LOG_STATUS, "Screenshot saved"); + return; + } +#endif + GBALog(gba, GBA_LOG_STATUS, "Failed to take screenshot"); +}
M src/gba/serialize.hsrc/gba/serialize.h

@@ -345,4 +345,6 @@ void GBARewindSettingsChanged(struct GBAThread* thread, int newCapacity, int newInterval);

int GBARewind(struct GBAThread* thread, int nStates); void GBARewindAll(struct GBAThread* thread); +void GBATakeScreenshot(struct GBA* gba, struct VDir* dir); + #endif
M src/gba/supervisor/thread.csrc/gba/supervisor/thread.c

@@ -16,7 +16,6 @@

#include "debugger/debugger.h" #include "util/patch.h" -#include "util/png-io.h" #include "util/vfs.h" #include "platform/commandline.h"

@@ -754,22 +753,9 @@ return TlsGetValue(_contextKey);

} #endif -#ifdef USE_PNG void GBAThreadTakeScreenshot(struct GBAThread* threadContext) { - unsigned stride; - const void* pixels = 0; - struct VFile* vf = VDirOptionalOpenIncrementFile(threadContext->stateDir, threadContext->gba->activeFile, "screenshot", "-", ".png", O_CREAT | O_TRUNC | O_WRONLY); - threadContext->gba->video.renderer->getPixels(threadContext->gba->video.renderer, &stride, &pixels); - png_structp png = PNGWriteOpen(vf); - png_infop info = PNGWriteHeader(png, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); - bool success = PNGWritePixels(png, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, stride, pixels); - PNGWriteClose(png, info); - vf->close(vf); - if (success) { - GBALog(threadContext->gba, GBA_LOG_STATUS, "Screenshot saved"); - } + GBATakeScreenshot(threadContext->gba, threadContext->stateDir); } -#endif #else struct GBAThread* GBAThreadGetContext(void) {
M src/util/vfs.csrc/util/vfs.c

@@ -167,3 +167,95 @@ vf = dir->openFile(dir, path, mode);

} return vf; } + +struct VFile* VDirOptionalOpenIncrementFile(struct VDir* dir, const char* realPath, const char* prefix, const char* infix, const char* suffix, int mode) { + char path[PATH_MAX]; + path[PATH_MAX - 1] = '\0'; + char realPrefix[PATH_MAX]; + realPrefix[PATH_MAX - 1] = '\0'; + if (!dir) { + if (!realPath) { + return 0; + } + const char* separatorPoint = strrchr(realPath, '/'); + const char* dotPoint; + size_t len; + if (!separatorPoint) { + strcpy(path, "./"); + separatorPoint = realPath; + dotPoint = strrchr(realPath, '.'); + } else { + path[0] = '\0'; + dotPoint = strrchr(separatorPoint, '.'); + + if (separatorPoint - realPath + 1 >= PATH_MAX - 1) { + return 0; + } + + len = separatorPoint - realPath; + strncat(path, realPath, len); + path[len] = '\0'; + ++separatorPoint; + } + + if (dotPoint - realPath + 1 >= PATH_MAX - 1) { + return 0; + } + + if (dotPoint >= separatorPoint) { + len = dotPoint - separatorPoint; + } else { + len = PATH_MAX - 1; + } + + strncpy(realPrefix, separatorPoint, len); + realPrefix[len] = '\0'; + + prefix = realPrefix; + dir = VDirOpen(path); + } + if (!dir) { + // This shouldn't be possible + return 0; + } + dir->rewind(dir); + struct VDirEntry* dirent; + size_t prefixLen = strlen(prefix); + size_t infixLen = strlen(infix); + unsigned next = 0; + while ((dirent = dir->listNext(dir))) { + const char* filename = dirent->name(dirent); + char* dotPoint = strrchr(filename, '.'); + size_t len = strlen(filename); + if (dotPoint) { + len = (dotPoint - filename); + } + const char* separator = strnrstr(filename, infix, len); + if (!separator) { + continue; + } + len = separator - filename; + if (len != prefixLen) { + continue; + } + if (strncmp(filename, prefix, prefixLen) == 0) { + int nlen; + separator += infixLen; + snprintf(path, PATH_MAX - 1, "%%u%s%%n", suffix); + unsigned increment; + if (sscanf(separator, path, &increment, &nlen) < 1) { + continue; + } + len = strlen(separator); + if (nlen < (ssize_t) len) { + continue; + } + if (next <= increment) { + next = increment + 1; + } + } + } + snprintf(path, PATH_MAX - 1, "%s%s%u%s", prefix, infix, next, suffix); + path[PATH_MAX - 1] = '\0'; + return dir->openFile(dir, path, mode); +}
M src/util/vfs/vfs-dirent.csrc/util/vfs/vfs-dirent.c

@@ -58,98 +58,6 @@

return &vd->d; } -struct VFile* VDirOptionalOpenIncrementFile(struct VDir* dir, const char* realPath, const char* prefix, const char* infix, const char* suffix, int mode) { - char path[PATH_MAX]; - path[PATH_MAX - 1] = '\0'; - char realPrefix[PATH_MAX]; - realPrefix[PATH_MAX - 1] = '\0'; - if (!dir) { - if (!realPath) { - return 0; - } - const char* separatorPoint = strrchr(realPath, '/'); - const char* dotPoint; - size_t len; - if (!separatorPoint) { - strcpy(path, "./"); - separatorPoint = realPath; - dotPoint = strrchr(realPath, '.'); - } else { - path[0] = '\0'; - dotPoint = strrchr(separatorPoint, '.'); - - if (separatorPoint - realPath + 1 >= PATH_MAX - 1) { - return 0; - } - - len = separatorPoint - realPath; - strncat(path, realPath, len); - path[len] = '\0'; - ++separatorPoint; - } - - if (dotPoint - realPath + 1 >= PATH_MAX - 1) { - return 0; - } - - if (dotPoint >= separatorPoint) { - len = dotPoint - separatorPoint; - } else { - len = PATH_MAX - 1; - } - - strncpy(realPrefix, separatorPoint, len); - realPrefix[len] = '\0'; - - prefix = realPrefix; - dir = VDirOpen(path); - } - if (!dir) { - // This shouldn't be possible - return 0; - } - dir->rewind(dir); - struct VDirEntry* dirent; - size_t prefixLen = strlen(prefix); - size_t infixLen = strlen(infix); - unsigned next = 0; - while ((dirent = dir->listNext(dir))) { - const char* filename = dirent->name(dirent); - char* dotPoint = strrchr(filename, '.'); - size_t len = strlen(filename); - if (dotPoint) { - len = (dotPoint - filename); - } - const char* separator = strnrstr(filename, infix, len); - if (!separator) { - continue; - } - len = separator - filename; - if (len != prefixLen) { - continue; - } - if (strncmp(filename, prefix, prefixLen) == 0) { - int nlen; - separator += infixLen; - snprintf(path, PATH_MAX - 1, "%%u%s%%n", suffix); - unsigned increment; - if (sscanf(separator, path, &increment, &nlen) < 1) { - continue; - } - len = strlen(separator); - if (nlen < (ssize_t) len) { - continue; - } - if (next <= increment) { - next = increment + 1; - } - } - } - snprintf(path, PATH_MAX - 1, "%s%s%u%s", prefix, infix, next, suffix); - path[PATH_MAX - 1] = '\0'; - return dir->openFile(dir, path, mode); -} - bool _vdClose(struct VDir* vd) { struct VDirDE* vdde = (struct VDirDE*) vd; if (closedir(vdde->de) < 0) {