mirror of https://github.com/mgba-emu/mgba.git
Restore pixels from PNG when loading savestate
This commit is contained in:
parent
a872bd3642
commit
b4d90e7e84
|
@ -130,11 +130,15 @@ static bool _loadPNGState(struct GBA* gba, struct VFile* vf) {
|
|||
PNGReadClose(png, info, end);
|
||||
return false;
|
||||
}
|
||||
uint32_t pixels[VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4];
|
||||
|
||||
PNGInstallChunkHandler(png, gba, _loadPNGChunkHandler, "gbAs");
|
||||
PNGReadHeader(png, info);
|
||||
PNGIgnorePixels(png, info);
|
||||
PNGReadPixels(png, info, &pixels, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, VIDEO_HORIZONTAL_PIXELS);
|
||||
PNGReadFooter(png, end);
|
||||
PNGReadClose(png, info, end);
|
||||
gba->video.renderer->putPixels(gba->video.renderer, VIDEO_HORIZONTAL_PIXELS, pixels);
|
||||
GBASyncPostFrame(gba->sync);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -535,6 +535,10 @@ void GBASyncPostFrame(struct GBASync* sync) {
|
|||
MutexUnlock(&sync->videoFrameMutex);
|
||||
|
||||
struct GBAThread* thread = GBAThreadGetContext();
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (thread->rewindBuffer) {
|
||||
--thread->rewindBufferNext;
|
||||
if (thread->rewindBufferNext <= 0) {
|
||||
|
@ -554,10 +558,12 @@ bool GBASyncWaitFrameStart(struct GBASync* sync, int frameskip) {
|
|||
|
||||
MutexLock(&sync->videoFrameMutex);
|
||||
ConditionWake(&sync->videoFrameRequiredCond);
|
||||
if (!sync->videoFrameOn) {
|
||||
if (!sync->videoFrameOn && !sync->videoFramePending) {
|
||||
return false;
|
||||
}
|
||||
ConditionWait(&sync->videoFrameAvailableCond, &sync->videoFrameMutex);
|
||||
if (!sync->videoFramePending) {
|
||||
ConditionWait(&sync->videoFrameAvailableCond, &sync->videoFrameMutex);
|
||||
}
|
||||
sync->videoFramePending = 0;
|
||||
sync->videoFrameSkip = frameskip;
|
||||
return true;
|
||||
|
|
|
@ -185,6 +185,7 @@ struct GBAVideoRenderer {
|
|||
void (*finishFrame)(struct GBAVideoRenderer* renderer);
|
||||
|
||||
void (*getPixels)(struct GBAVideoRenderer* renderer, unsigned* stride, void** pixels);
|
||||
void (*putPixels)(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels);
|
||||
|
||||
uint16_t* palette;
|
||||
uint16_t* vram;
|
||||
|
|
|
@ -30,6 +30,7 @@ static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRender
|
|||
static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* renderer, int y);
|
||||
static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer);
|
||||
static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer, unsigned* stride, void** pixels);
|
||||
static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels);
|
||||
|
||||
static void GBAVideoSoftwareRendererUpdateDISPCNT(struct GBAVideoSoftwareRenderer* renderer);
|
||||
static void GBAVideoSoftwareRendererWriteBGCNT(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* bg, uint16_t value);
|
||||
|
@ -69,6 +70,7 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
|
|||
renderer->d.drawScanline = GBAVideoSoftwareRendererDrawScanline;
|
||||
renderer->d.finishFrame = GBAVideoSoftwareRendererFinishFrame;
|
||||
renderer->d.getPixels = GBAVideoSoftwareRendererGetPixels;
|
||||
renderer->d.putPixels = GBAVideoSoftwareRendererPutPixels;
|
||||
}
|
||||
|
||||
static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) {
|
||||
|
@ -510,6 +512,16 @@ static void GBAVideoSoftwareRendererGetPixels(struct GBAVideoRenderer* renderer,
|
|||
*pixels = softwareRenderer->outputBuffer;
|
||||
}
|
||||
|
||||
static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, unsigned stride, void* pixels) {
|
||||
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
|
||||
|
||||
uint32_t* colorPixels = pixels;
|
||||
unsigned i;
|
||||
for (i = 0; i < VIDEO_VERTICAL_PIXELS; ++i) {
|
||||
memmove(&softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * i], &colorPixels[stride * i], VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL);
|
||||
}
|
||||
}
|
||||
|
||||
static void GBAVideoSoftwareRendererUpdateDISPCNT(struct GBAVideoSoftwareRenderer* renderer) {
|
||||
renderer->bg[0].enabled = renderer->dispcnt.bg0Enable;
|
||||
renderer->bg[1].enabled = renderer->dispcnt.bg1Enable;
|
||||
|
|
|
@ -135,6 +135,37 @@ bool PNGIgnorePixels(png_structp png, png_infop info) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) {
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* pixelData = pixels;
|
||||
unsigned pngHeight = png_get_image_height(png, info);
|
||||
if (height > pngHeight) {
|
||||
height = pngHeight;
|
||||
}
|
||||
|
||||
unsigned pngWidth = png_get_image_width(png, info);
|
||||
if (width > pngWidth) {
|
||||
width = pngWidth;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
png_bytep row = malloc(png_get_rowbytes(png, info));
|
||||
for (i = 0; i < height; ++i) {
|
||||
png_read_row(png, row, 0);
|
||||
unsigned x;
|
||||
for (x = 0; x < width; ++x) {
|
||||
pixelData[stride * i * 4 + x * 4] = row[x * 3];
|
||||
pixelData[stride * i * 4 + x * 4 + 1] = row[x * 3 + 1];
|
||||
pixelData[stride * i * 4 + x * 4 + 2] = row[x * 3 + 2];
|
||||
}
|
||||
}
|
||||
free(row);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PNGReadFooter(png_structp png, png_infop end) {
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
return false;
|
||||
|
|
|
@ -23,6 +23,7 @@ bool isPNG(struct VFile* source);
|
|||
png_structp PNGReadOpen(struct VFile* source, unsigned offset);
|
||||
bool PNGInstallChunkHandler(png_structp png, void* context, ChunkHandler handler, const char* chunkName);
|
||||
bool PNGReadHeader(png_structp png, png_infop info);
|
||||
bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride);
|
||||
bool PNGIgnorePixels(png_structp png, png_infop info);
|
||||
bool PNGReadFooter(png_structp png, png_infop end);
|
||||
void PNGReadClose(png_structp png, png_infop info, png_infop end);
|
||||
|
|
Loading…
Reference in New Issue