GBA RR: Add preliminary SRAM support for VBM loading

This commit is contained in:
Jeffrey Pfau 2016-01-04 01:14:44 -08:00
parent bfd73a793d
commit 0e8e55e8ed
2 changed files with 77 additions and 5 deletions

View File

@ -51,6 +51,7 @@ Misc:
- GBA RR: Starting from savestate now embeds the savegame
- Libretro: Add install target for libretro core
- 3DS: Update to new ctrulib API
- GBA RR: Add preliminary SRAM support for VBM loading
0.3.2: (2015-12-16)
Bugfixes:

View File

@ -9,6 +9,10 @@
#include "gba/serialize.h"
#include "util/vfs.h"
#ifdef USE_ZLIB
#include <zlib.h>
#endif
static const char VBM_MAGIC[] = "VBM\x1A";
static void GBAVBMContextDestroy(struct GBARRContext*);
@ -125,9 +129,72 @@ void GBAVBMStateLoaded(struct GBARRContext* rr, const struct GBASerializedState*
}
struct VFile* GBAVBMOpenSavedata(struct GBARRContext* rr, int flags) {
UNUSED(rr);
UNUSED(flags);
#ifndef USE_ZLIB
UNUSED(rr);
return 0;
#else
struct GBAVBMContext* vbm = (struct GBAVBMContext*) rr;
off_t pos = vbm->vbmFile->seek(vbm->vbmFile, 0, SEEK_CUR);
uint32_t saveType, flashSize, sramOffset;
vbm->vbmFile->seek(vbm->vbmFile, 0x18, SEEK_SET);
vbm->vbmFile->read(vbm->vbmFile, &saveType, sizeof(saveType));
vbm->vbmFile->read(vbm->vbmFile, &flashSize, sizeof(flashSize));
vbm->vbmFile->seek(vbm->vbmFile, 0x38, SEEK_SET);
vbm->vbmFile->read(vbm->vbmFile, &sramOffset, sizeof(sramOffset));
if (!sramOffset) {
vbm->vbmFile->seek(vbm->vbmFile, pos, SEEK_SET);
return 0;
}
vbm->vbmFile->seek(vbm->vbmFile, sramOffset, SEEK_SET);
struct VFile* save = VFileMemChunk(0, 0);
size_t size;
switch (saveType) {
case 1:
size = SIZE_CART_SRAM;
break;
case 2:
size = flashSize;
if (size > SIZE_CART_FLASH1M) {
size = SIZE_CART_FLASH1M;
}
break;
case 3:
size = SIZE_CART_EEPROM;
break;
default:
size = SIZE_CART_FLASH1M;
break;
}
uLong zlen = vbm->inputOffset - sramOffset;
char buffer[8761];
char* zbuffer = malloc(zlen);
vbm->vbmFile->read(vbm->vbmFile, zbuffer, zlen);
z_stream zstr;
zstr.zalloc = Z_NULL;
zstr.zfree = Z_NULL;
zstr.opaque = Z_NULL;
zstr.avail_in = zlen;
zstr.next_in = (Bytef*) zbuffer;
zstr.avail_out = 0;
inflateInit2(&zstr, 31);
// Skip header, we know where the save file is
zstr.avail_out = sizeof(buffer);
zstr.next_out = (Bytef*) &buffer;
int err = inflate(&zstr, 0);
while (err != Z_STREAM_END && !zstr.avail_out) {
zstr.avail_out = sizeof(buffer);
zstr.next_out = (Bytef*) &buffer;
int err = inflate(&zstr, 0);
if (err < 0) {
break;
}
save->write(save, buffer, sizeof(buffer) - zstr.avail_out);
}
inflateEnd(&zstr);
vbm->vbmFile->seek(vbm->vbmFile, pos, SEEK_SET);
return save;
#endif
}
struct VFile* GBAVBMOpenSavestate(struct GBARRContext* rr, int flags) {
@ -163,14 +230,18 @@ bool GBAVBMSetStream(struct GBAVBMContext* vbm, struct VFile* vf) {
uint8_t flags;
vf->read(vf, &flags, sizeof(flags));
if (flags & 2) {
#if USE_ZLIB
vbm->d.initFrom = INIT_FROM_SAVEGAME;
#else
// zlib is needed to parse the savegame
return false;
#endif
}
if (flags & 1) {
// Incompatible savestate format
return false;
}
if (flags & 2) {
// TODO: Implement SRAM loading
return false;
}
vf->seek(vf, 1, SEEK_CUR);
vf->read(vf, &flags, sizeof(flags));