mirror of https://github.com/mgba-emu/mgba.git
GUI: Make savestate screens show the relevant savestate picture
This commit is contained in:
parent
9b14cc607d
commit
cb8d60e211
|
@ -10,6 +10,8 @@
|
|||
#include "util/gui/file-select.h"
|
||||
#include "util/gui/font.h"
|
||||
#include "util/gui/menu.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/png-io.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
enum {
|
||||
|
@ -30,13 +32,46 @@ enum {
|
|||
RUNNER_STATE_9 = 0x90000,
|
||||
};
|
||||
|
||||
static void _drawBackground(struct GUIBackground* background) {
|
||||
static void _drawBackground(struct GUIBackground* background, void* context) {
|
||||
UNUSED(context);
|
||||
struct GBAGUIBackground* gbaBackground = (struct GBAGUIBackground*) background;
|
||||
if (gbaBackground->p->drawFrame) {
|
||||
gbaBackground->p->drawFrame(gbaBackground->p, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void _drawState(struct GUIBackground* background, void* id) {
|
||||
struct GBAGUIBackground* gbaBackground = (struct GBAGUIBackground*) background;
|
||||
int stateId = ((int) id) >> 16;
|
||||
if (gbaBackground->p->drawScreenshot) {
|
||||
struct VFile* vf = GBAGetState(gbaBackground->p->context.gba, 0, stateId, false);
|
||||
uint32_t* pixels = anonymousMemoryMap(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4);
|
||||
bool success = false;
|
||||
if (vf && isPNG(vf) && pixels) {
|
||||
png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES);
|
||||
png_infop info = png_create_info_struct(png);
|
||||
png_infop end = png_create_info_struct(png);
|
||||
if (png && info && end) {
|
||||
success = PNGReadHeader(png, info);
|
||||
success = success && PNGReadPixels(png, info, pixels, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, VIDEO_HORIZONTAL_PIXELS);
|
||||
success = success && PNGReadFooter(png, end);
|
||||
}
|
||||
PNGReadClose(png, info, end);
|
||||
}
|
||||
if (vf) {
|
||||
vf->close(vf);
|
||||
}
|
||||
if (success) {
|
||||
gbaBackground->p->drawScreenshot(gbaBackground->p, pixels, true);
|
||||
} else if (gbaBackground->p->drawFrame) {
|
||||
gbaBackground->p->drawFrame(gbaBackground->p, true);
|
||||
}
|
||||
if (pixels) {
|
||||
mappedMemoryFree(pixels, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _updateLux(struct GBALuminanceSource* lux) {
|
||||
UNUSED(lux);
|
||||
}
|
||||
|
@ -72,6 +107,12 @@ void GBAGUIDeinit(struct GBAGUIRunner* runner) {
|
|||
}
|
||||
|
||||
void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
||||
struct GBAGUIBackground drawState = {
|
||||
.d = {
|
||||
.draw = _drawState
|
||||
},
|
||||
.p = runner
|
||||
};
|
||||
struct GUIMenu pauseMenu = {
|
||||
.title = "Game Paused",
|
||||
.index = 0,
|
||||
|
@ -80,12 +121,12 @@ void GBAGUIRunloop(struct GBAGUIRunner* runner) {
|
|||
struct GUIMenu stateSaveMenu = {
|
||||
.title = "Save state",
|
||||
.index = 0,
|
||||
.background = &runner->background.d
|
||||
.background = &drawState.d
|
||||
};
|
||||
struct GUIMenu stateLoadMenu = {
|
||||
.title = "Load state",
|
||||
.index = 0,
|
||||
.background = &runner->background.d
|
||||
.background = &drawState.d
|
||||
};
|
||||
GUIMenuItemListInit(&pauseMenu.items, 0);
|
||||
GUIMenuItemListInit(&stateSaveMenu.items, 9);
|
||||
|
|
|
@ -37,6 +37,7 @@ struct GBAGUIRunner {
|
|||
void (*gameUnloaded)(struct GBAGUIRunner*);
|
||||
void (*prepareForFrame)(struct GBAGUIRunner*);
|
||||
void (*drawFrame)(struct GBAGUIRunner*, bool faded);
|
||||
void (*drawScreenshot)(struct GBAGUIRunner*, const uint32_t* pixels, bool faded);
|
||||
void (*paused)(struct GBAGUIRunner*);
|
||||
void (*unpaused)(struct GBAGUIRunner*);
|
||||
uint16_t (*pollGameInput)(struct GBAGUIRunner*);
|
||||
|
|
|
@ -112,15 +112,39 @@ static void _gameUnloaded(struct GBAGUIRunner* runner) {
|
|||
}
|
||||
|
||||
static void _drawFrame(struct GBAGUIRunner* runner, bool faded) {
|
||||
UNUSED(runner);
|
||||
GSPGPU_FlushDataCache(0, renderer.outputBuffer, 256 * VIDEO_VERTICAL_PIXELS * 2);
|
||||
GX_SetDisplayTransfer(0, renderer.outputBuffer, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), 0x000002202);
|
||||
gspWaitForPPF();
|
||||
GSPGPU_FlushDataCache(0, tex->data, 256 * VIDEO_VERTICAL_PIXELS * 2);
|
||||
sf2d_draw_texture_scale_blend(tex, 40, 296, 1, -1, 0xFFFFFF3F | (faded ? 0 : 0xC0));
|
||||
#if RESAMPLE_LIBRARY == RESAMPLE_BLIP_BUF
|
||||
if (!hasSound) {
|
||||
blip_clear(runner->context.gba->audio.left);
|
||||
blip_clear(runner->context.gba->audio.right);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _drawScreenshot(struct GBAGUIRunner* runner, const uint32_t* pixels, bool faded) {
|
||||
UNUSED(runner);
|
||||
u16* newPixels = linearMemAlign(256 * VIDEO_VERTICAL_PIXELS * 2, 0x80);
|
||||
unsigned y, x;
|
||||
for (y = 0; y < VIDEO_VERTICAL_PIXELS; ++y) {
|
||||
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) {
|
||||
u16 pixel = (*pixels >> 19) & 0x1F;
|
||||
pixel |= (*pixels >> 5) & 0x7C0;
|
||||
pixel |= (*pixels << 8) & 0xF800;
|
||||
newPixels[y * 256 + x] = pixel;
|
||||
++pixels;
|
||||
}
|
||||
memset(&newPixels[y * 256 + VIDEO_HORIZONTAL_PIXELS], 0, 32);
|
||||
}
|
||||
GSPGPU_FlushDataCache(0, (void*) newPixels, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 2);
|
||||
GX_SetDisplayTransfer(0, (void*) newPixels, GX_BUFFER_DIM(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS), tex->data, GX_BUFFER_DIM(256, VIDEO_VERTICAL_PIXELS), 0x000002202);
|
||||
gspWaitForPPF();
|
||||
linearFree(newPixels);
|
||||
GSPGPU_FlushDataCache(0, (void*) tex->data, 256 * VIDEO_VERTICAL_PIXELS * 2);
|
||||
sf2d_draw_texture_scale_blend(tex, 40, 296, 1, -1, 0xFFFFFF3F | (faded ? 0 : 0xC0));
|
||||
}
|
||||
|
||||
|
@ -264,6 +288,7 @@ int main() {
|
|||
.gameUnloaded = _gameUnloaded,
|
||||
.prepareForFrame = 0,
|
||||
.drawFrame = _drawFrame,
|
||||
.drawScreenshot = _drawScreenshot,
|
||||
.paused = _gameUnloaded,
|
||||
.unpaused = _gameLoaded,
|
||||
.pollGameInput = _pollGameInput
|
||||
|
|
|
@ -29,7 +29,7 @@ enum GUIInput {
|
|||
};
|
||||
|
||||
struct GUIBackground {
|
||||
void (*draw)(struct GUIBackground*);
|
||||
void (*draw)(struct GUIBackground*, void* context);
|
||||
};
|
||||
|
||||
struct GUIParams {
|
||||
|
|
|
@ -71,7 +71,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
|||
|
||||
params->drawStart();
|
||||
if (menu->background) {
|
||||
menu->background->draw(menu->background);
|
||||
menu->background->draw(menu->background, GUIMenuItemListGetPointer(&menu->items, menu->index)->data);
|
||||
}
|
||||
if (params->guiPrepare) {
|
||||
params->guiPrepare();
|
||||
|
|
Loading…
Reference in New Issue