GB: Fix uninitialized save data when loading undersized temporary saves

This commit is contained in:
Vicki Pfau 2024-01-21 02:17:25 -08:00
parent 7157729ac3
commit 12ed251c0b
2 changed files with 28 additions and 8 deletions

View File

@ -16,6 +16,7 @@ Emulation fixes:
Other fixes: Other fixes:
- Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963) - Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963)
- Debugger: Fix writing to specific segment in command-line debugger - Debugger: Fix writing to specific segment in command-line debugger
- GB: Fix uninitialized save data when loading undersized temporary saves
- Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560) - Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560)
Misc: Misc:
- Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826) - Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826)

View File

@ -260,9 +260,13 @@ void GBResizeSram(struct GB* gb, size_t size) {
} }
struct VFile* vf = gb->sramVf; struct VFile* vf = gb->sramVf;
if (vf) { if (vf) {
if (vf == gb->sramRealVf) { // We have a vf
ssize_t vfSize = vf->size(vf); ssize_t vfSize = vf->size(vf);
if (vf == gb->sramRealVf) {
// This is the real save file, not a masked one
if (vfSize >= 0 && (size_t) vfSize < size) { if (vfSize >= 0 && (size_t) vfSize < size) {
// We need to grow the file
// Make sure to copy the footer data, if any
uint8_t extdataBuffer[0x100]; uint8_t extdataBuffer[0x100];
if (vfSize & 0xFF) { if (vfSize & 0xFF) {
vf->seek(vf, -(vfSize & 0xFF), SEEK_END); vf->seek(vf, -(vfSize & 0xFF), SEEK_END);
@ -270,6 +274,7 @@ void GBResizeSram(struct GB* gb, size_t size) {
} }
if (gb->memory.sram) { if (gb->memory.sram) {
vf->unmap(vf, gb->memory.sram, gb->sramSize); vf->unmap(vf, gb->memory.sram, gb->sramSize);
gb->memory.sram = NULL;
} }
vf->truncate(vf, size + (vfSize & 0xFF)); vf->truncate(vf, size + (vfSize & 0xFF));
if (vfSize & 0xFF) { if (vfSize & 0xFF) {
@ -281,24 +286,36 @@ void GBResizeSram(struct GB* gb, size_t size) {
memset(&gb->memory.sram[vfSize], 0xFF, size - vfSize); memset(&gb->memory.sram[vfSize], 0xFF, size - vfSize);
} }
} else if (size > gb->sramSize || !gb->memory.sram) { } else if (size > gb->sramSize || !gb->memory.sram) {
// We aren't growing the file, but we are changing our mapping of it
if (gb->memory.sram) { if (gb->memory.sram) {
vf->unmap(vf, gb->memory.sram, gb->sramSize); vf->unmap(vf, gb->memory.sram, gb->sramSize);
gb->memory.sram = NULL;
} }
if (size) { if (size) {
gb->memory.sram = vf->map(vf, size, MAP_WRITE); gb->memory.sram = vf->map(vf, size, MAP_WRITE);
} }
} }
} else { } else {
// This is a masked save file
if (gb->memory.sram) { if (gb->memory.sram) {
vf->unmap(vf, gb->memory.sram, gb->sramSize); vf->unmap(vf, gb->memory.sram, gb->sramSize);
} }
if (vf->size(vf) < gb->sramSize) { if ((vfSize <= 0 && size) || (size_t) vfSize < size) {
void* sram = vf->map(vf, vf->size(vf), MAP_READ); // The loaded mask file is too small. Since these can be read-only,
struct VFile* newVf = VFileMemChunk(sram, vf->size(vf)); // we need to make a new one of the right size
vf->unmap(vf, sram,vf->size(vf)); if (vfSize < 0) {
vf = newVf; vfSize = 0;
gb->sramVf = newVf; }
vf->truncate(vf, size); gb->sramVf = VFileMemChunk(NULL, size);
uint8_t* sram = gb->sramVf->map(gb->sramVf, size, MAP_WRITE);
if (vfSize > 0) {
vf->seek(vf, 0, SEEK_SET);
vf->read(vf, sram, vfSize);
}
memset(&sram[vfSize], 0xFF, size - vfSize);
gb->sramVf->unmap(gb->sramVf, sram, size);
vf->close(vf);
vf = gb->sramVf;
} }
if (size) { if (size) {
gb->memory.sram = vf->map(vf, size, MAP_READ); gb->memory.sram = vf->map(vf, size, MAP_READ);
@ -308,6 +325,8 @@ void GBResizeSram(struct GB* gb, size_t size) {
gb->memory.sram = NULL; gb->memory.sram = NULL;
} }
} else if (size) { } else if (size) {
// There's no vf, so let's make it only memory-backed
// TODO: Investigate just using a VFileMemChunk instead of this hybrid approach
uint8_t* newSram = anonymousMemoryMap(size); uint8_t* newSram = anonymousMemoryMap(size);
if (gb->memory.sram) { if (gb->memory.sram) {
if (size > gb->sramSize) { if (size > gb->sramSize) {