mirror of https://github.com/mgba-emu/mgba.git
GB: Fix uninitialized save data when loading undersized temporary saves
This commit is contained in:
parent
7157729ac3
commit
12ed251c0b
1
CHANGES
1
CHANGES
|
@ -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)
|
||||||
|
|
35
src/gb/gb.c
35
src/gb/gb.c
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue