mirror of https://github.com/mgba-emu/mgba.git
mGUI: Cache save state screenshot validity in state menu (fixes #2005)
This commit is contained in:
parent
ccafcf7bdc
commit
c6aa7c6673
1
CHANGES
1
CHANGES
|
@ -23,6 +23,7 @@ Other fixes:
|
||||||
- GB Audio: Fix audio channel 4 being slow to deserialize
|
- GB Audio: Fix audio channel 4 being slow to deserialize
|
||||||
- GB Core: Fix GBC colors setting breaking default model overrides (fixes mgba.io/i/2161)
|
- GB Core: Fix GBC colors setting breaking default model overrides (fixes mgba.io/i/2161)
|
||||||
- GBA: Fix out of bounds ROM accesses on patched ROMs smaller than 32 MiB
|
- GBA: Fix out of bounds ROM accesses on patched ROMs smaller than 32 MiB
|
||||||
|
- mGUI: Cache save state screenshot validity in state menu (fixes mgba.io/i/2005)
|
||||||
- Qt: Fix infrequent deadlock when using sync to video
|
- Qt: Fix infrequent deadlock when using sync to video
|
||||||
- Qt: Fix applying savetype-only overrides
|
- Qt: Fix applying savetype-only overrides
|
||||||
- Qt: Fix crash in sprite view for partially out-of-bounds sprites (fixes mgba.io/i/2165)
|
- Qt: Fix crash in sprite view for partially out-of-bounds sprites (fixes mgba.io/i/2165)
|
||||||
|
|
|
@ -42,6 +42,11 @@ enum {
|
||||||
|
|
||||||
#define RUNNER_STATE(X) ((X) << 16)
|
#define RUNNER_STATE(X) ((X) << 16)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SCREENSHOT_VALID = 0x10000,
|
||||||
|
SCREENSHOT_INVALID = 0x20000,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mInputPlatformInfo _mGUIKeyInfo = {
|
static const struct mInputPlatformInfo _mGUIKeyInfo = {
|
||||||
.platformName = "gui",
|
.platformName = "gui",
|
||||||
.keyId = (const char*[GUI_INPUT_MAX]) {
|
.keyId = (const char*[GUI_INPUT_MAX]) {
|
||||||
|
@ -107,39 +112,49 @@ static void _drawBackground(struct GUIBackground* background, void* context) {
|
||||||
|
|
||||||
static void _drawState(struct GUIBackground* background, void* id) {
|
static void _drawState(struct GUIBackground* background, void* id) {
|
||||||
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
|
struct mGUIBackground* gbaBackground = (struct mGUIBackground*) background;
|
||||||
int stateId = ((int) id) >> 16;
|
unsigned stateId = ((uint32_t) id) >> 16;
|
||||||
if (gbaBackground->p->drawScreenshot) {
|
if (gbaBackground->p->drawScreenshot) {
|
||||||
unsigned w, h;
|
unsigned w, h;
|
||||||
gbaBackground->p->core->desiredVideoDimensions(gbaBackground->p->core, &w, &h);
|
gbaBackground->p->core->desiredVideoDimensions(gbaBackground->p->core, &w, &h);
|
||||||
if (gbaBackground->screenshot && gbaBackground->screenshotId == (int) id) {
|
size_t size = w * h * BYTES_PER_PIXEL;
|
||||||
gbaBackground->p->drawScreenshot(gbaBackground->p, gbaBackground->screenshot, w, h, true);
|
if (size != gbaBackground->imageSize) {
|
||||||
|
mappedMemoryFree(gbaBackground->image, gbaBackground->imageSize);
|
||||||
|
gbaBackground->image = NULL;
|
||||||
|
}
|
||||||
|
if (gbaBackground->image && gbaBackground->screenshotId == (stateId | SCREENSHOT_VALID)) {
|
||||||
|
gbaBackground->p->drawScreenshot(gbaBackground->p, gbaBackground->image, w, h, true);
|
||||||
return;
|
return;
|
||||||
}
|
} else if (gbaBackground->screenshotId != (stateId | SCREENSHOT_INVALID)) {
|
||||||
struct VFile* vf = mCoreGetState(gbaBackground->p->core, stateId, false);
|
struct VFile* vf = mCoreGetState(gbaBackground->p->core, stateId, false);
|
||||||
color_t* pixels = gbaBackground->screenshot;
|
color_t* pixels = gbaBackground->image;
|
||||||
if (!pixels) {
|
if (!pixels) {
|
||||||
pixels = anonymousMemoryMap(w * h * 4);
|
pixels = anonymousMemoryMap(size);
|
||||||
gbaBackground->screenshot = pixels;
|
gbaBackground->image = pixels;
|
||||||
}
|
gbaBackground->imageSize = size;
|
||||||
bool success = false;
|
}
|
||||||
if (vf && isPNG(vf) && pixels) {
|
bool success = false;
|
||||||
png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES);
|
if (vf && isPNG(vf) && pixels) {
|
||||||
png_infop info = png_create_info_struct(png);
|
png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES);
|
||||||
png_infop end = png_create_info_struct(png);
|
png_infop info = png_create_info_struct(png);
|
||||||
if (png && info && end) {
|
png_infop end = png_create_info_struct(png);
|
||||||
success = PNGReadHeader(png, info);
|
if (png && info && end) {
|
||||||
success = success && PNGReadPixels(png, info, pixels, w, h, w);
|
success = PNGReadHeader(png, info);
|
||||||
success = success && PNGReadFooter(png, end);
|
success = success && PNGReadPixels(png, info, pixels, w, h, w);
|
||||||
|
success = success && PNGReadFooter(png, end);
|
||||||
|
}
|
||||||
|
PNGReadClose(png, info, end);
|
||||||
|
}
|
||||||
|
if (vf) {
|
||||||
|
vf->close(vf);
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, w, h, true);
|
||||||
|
gbaBackground->screenshotId = stateId | SCREENSHOT_VALID;
|
||||||
|
} else {
|
||||||
|
gbaBackground->screenshotId = stateId | SCREENSHOT_INVALID;
|
||||||
}
|
}
|
||||||
PNGReadClose(png, info, end);
|
|
||||||
}
|
}
|
||||||
if (vf) {
|
if (gbaBackground->p->drawFrame && gbaBackground->screenshotId == (stateId | SCREENSHOT_INVALID)) {
|
||||||
vf->close(vf);
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, w, h, true);
|
|
||||||
gbaBackground->screenshotId = (int) id;
|
|
||||||
} else if (gbaBackground->p->drawFrame) {
|
|
||||||
gbaBackground->p->drawFrame(gbaBackground->p, true);
|
gbaBackground->p->drawFrame(gbaBackground->p, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +330,7 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
.draw = _drawState
|
.draw = _drawState
|
||||||
},
|
},
|
||||||
.p = runner,
|
.p = runner,
|
||||||
.screenshot = 0,
|
.image = 0,
|
||||||
.screenshotId = 0
|
.screenshotId = 0
|
||||||
};
|
};
|
||||||
struct GUIMenu pauseMenu = {
|
struct GUIMenu pauseMenu = {
|
||||||
|
@ -628,10 +643,10 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
runner->core->reset(runner->core);
|
runner->core->reset(runner->core);
|
||||||
break;
|
break;
|
||||||
case RUNNER_SAVE_STATE:
|
case RUNNER_SAVE_STATE:
|
||||||
mCoreSaveState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA);
|
mCoreSaveState(runner->core, ((uint32_t) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_METADATA);
|
||||||
break;
|
break;
|
||||||
case RUNNER_LOAD_STATE:
|
case RUNNER_LOAD_STATE:
|
||||||
mCoreLoadState(runner->core, ((int) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
|
mCoreLoadState(runner->core, ((uint32_t) item->data) >> 16, SAVESTATE_SCREENSHOT | SAVESTATE_RTC);
|
||||||
break;
|
break;
|
||||||
case RUNNER_SCREENSHOT:
|
case RUNNER_SCREENSHOT:
|
||||||
mCoreTakeScreenshot(runner->core);
|
mCoreTakeScreenshot(runner->core);
|
||||||
|
@ -696,10 +711,8 @@ void mGUIRun(struct mGUIRunner* runner, const char* path) {
|
||||||
mLOG(GUI_RUNNER, DEBUG, "Unloading game...");
|
mLOG(GUI_RUNNER, DEBUG, "Unloading game...");
|
||||||
runner->core->unloadROM(runner->core);
|
runner->core->unloadROM(runner->core);
|
||||||
drawState.screenshotId = 0;
|
drawState.screenshotId = 0;
|
||||||
if (drawState.screenshot) {
|
if (drawState.image) {
|
||||||
unsigned w, h;
|
mappedMemoryFree(drawState.image, drawState.imageSize);
|
||||||
runner->core->desiredVideoDimensions(runner->core, &w, &h);
|
|
||||||
mappedMemoryFree(drawState.screenshot, w * h * 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runner->config.port) {
|
if (runner->config.port) {
|
||||||
|
|
|
@ -31,8 +31,10 @@ struct mGUIBackground {
|
||||||
struct GUIBackground d;
|
struct GUIBackground d;
|
||||||
struct mGUIRunner* p;
|
struct mGUIRunner* p;
|
||||||
|
|
||||||
color_t* screenshot;
|
color_t* image;
|
||||||
int screenshotId;
|
size_t imageSize;
|
||||||
|
|
||||||
|
unsigned screenshotId;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mCore;
|
struct mCore;
|
||||||
|
|
Loading…
Reference in New Issue